﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SCMS.CoreBusinessLogic.Budgeting;
using SCMS.CoreBusinessLogic.OrderRequest;
using SCMS.CoreBusinessLogic.PurchaseOrder;
using SCMS.CoreBusinessLogic.TenderAnalysis;
using SCMS.CoreBusinessLogic.Web;
using SCMS.Model;
using System.Text;
using SCMS.CoreBusinessLogic.Request4Payment;
using SCMS.CoreBusinessLogic.StaffServices;
using SCMS.CoreBusinessLogic.Security;
using SCMS.CoreBusinessLogic.ActionFilters;
using SCMS.CoreBusinessLogic.NotificationsManager;
using SCMS.CoreBusinessLogic.Request4Advance;
using SCMS.CoreBusinessLogic.WRF;
using SCMS.CoreBusinessLogic.ExpenseClaim;
using SCMS.CoreBusinessLogic.SalaryPayment;
using SCMS.CoreBusinessLogic._ExchangeRate;
using SCMS.CoreBusinessLogic._GoodsReceivedNote;
using SCMS.CoreBusinessLogic.TravelAuthorisation;
using SCMS.UI.Models;
using SCMS.CoreBusinessLogic.ProcurementPlan;
using SCMS.CoreBusinessLogic.CompletionCtificate;
using SCMS.Resource;

namespace SCMS.UI.Controllers
{
    [MyException]
    public class RequestReviewController : PortalBaseController
    {
        #region .Private Variables.

        private IOrderRequest orderRequestService;
        private IPurchaseOrderService purchaseOrderService;
        private ITAnalysisService tAnalysisService;
        private IBudgetService budgetService;
        private IMasterBudgetService masterBudgetService;
        private IRequest4PaymentService request4PaymentService;
        private IStaffService staffService;
        private INotificationService notificationService;
        private IRequest4Advance rfaService;
        private IWareHouseReleaseService wroService;
        private IExpenseClaimService expenseClaimService;
        private ISalaryPaymentService salaryPaymentService;
        private IExchangeRateService exchangeRateService;
        private IGoodsReceivedNoteService grnService;
        private ITravelAuthService tafService;
        private IProcurementPlanService ppService;
        private ICompletionCertificateService ccService;

        #endregion

        #region .Constructor.

        public RequestReviewController(IPermissionService permissionService, IUserContext userContext, IOrderRequest orderRequestService, IPurchaseOrderService purchaseOrderService, ITAnalysisService tAnalysisService,
            IBudgetService budgetService, IMasterBudgetService masterBudgetService, IRequest4PaymentService request4PaymentService, IStaffService staffService,
            INotificationService notificationService, IRequest4Advance rfaService, IWareHouseReleaseService wrnService, IExpenseClaimService expenseClaimService,
            ISalaryPaymentService salaryPaymentService, IExchangeRateService exchangeRateService, IGoodsReceivedNoteService grnService, ITravelAuthService tafService,
            IProcurementPlanService ppService, ICompletionCertificateService ccService)
            : base(userContext, permissionService)
        {
            this.budgetService = budgetService;
            this.masterBudgetService = masterBudgetService;
            this.orderRequestService = orderRequestService;
            this.purchaseOrderService = purchaseOrderService;
            this.tAnalysisService = tAnalysisService;
            this.request4PaymentService = request4PaymentService;
            this.staffService = staffService;
            this.notificationService = notificationService;
            this.rfaService = rfaService;
            this.wroService = wrnService;
            this.expenseClaimService = expenseClaimService;
            this.salaryPaymentService = salaryPaymentService;
            this.exchangeRateService = exchangeRateService;
            this.grnService = grnService;
            this.tafService = tafService;
            this.ppService = ppService;
            this.ccService = ccService;
        }

        #endregion
        //
        // GET: /RequestReview/

        public ActionResult Index()
        {
            return View();
        }

        #region .Load Requests.

        public ActionResult GetRequests()
        {

            //REQUESTS FOR APPROVAL
            List<Model.OrderRequest> orderRequests = new List<Model.OrderRequest>();

            orderRequests = orderRequestService.GetOrderRequestsForApproval(currentUser);
            List<Models.ViewOR> viewORList = ConstructORequestListForNotification(orderRequests);

            //Add lists to ReviewModel to be included in Notificaion Menu
            Models.RequestReviewModel rrModel = new Models.RequestReviewModel();
            rrModel.ApprovalOrderRequests = viewORList;

            //REQUESTS FOR REVIEW
            List<Model.PurchaseOrder> purchaseOrders = new List<PurchaseOrder>();
            List<Model.TenderAnalysi> tenderAnalyses = new List<TenderAnalysi>();
            List<Model.PaymentRequest> paymentRequests = new List<PaymentRequest>();
            List<Model.AdvanceRequest> advanceRequests = new List<AdvanceRequest>();
            List<Model.SalaryRequest> salaryRequests = new List<SalaryRequest>();
            List<Model.ExpenseRequest> expenseClaims = new List<ExpenseRequest>();
            List<Model.WarehouseRelease> warehouseReleases = new List<WarehouseRelease>();
            List<Model.GoodsReceivedNote> goodsReceivedNotes = new List<GoodsReceivedNote>();
            List<TravelAuthorization> travelAuthorizations = new List<TravelAuthorization>();
            List<Model.ProcurementPlan> procurementPlans = new List<ProcurementPlan>();
            List<Model.CompletionCertificate> completionCertificates = new List<CompletionCertificate>();

            orderRequests = orderRequestService.GetOrderRequestsForReview(currentUser);
            purchaseOrders = purchaseOrderService.GetPurchaseOrdersForReview(currentUser);
            tenderAnalyses = tAnalysisService.GetTenderAnalysesForEval(currentUser);
            paymentRequests = request4PaymentService.GetPaymentRequests4Review(currentUser);
            advanceRequests = rfaService.GetAdvanceRequestsForReview(currentUser);
            warehouseReleases = wroService.GetWRNsForApproval(currentStaff);
            expenseClaims = expenseClaimService.GetExpenseClaimsForReview(currentUser);
            salaryRequests = salaryPaymentService.GetSalaryPaymentsForReview(currentUser);
            goodsReceivedNotes = grnService.GetGRNsForApproval(currentStaff);
            travelAuthorizations = tafService.GetTravelAuthorizationsForReview(currentUser);
            procurementPlans = ppService.GetPPForApproval(currentUser);
            completionCertificates = ccService.GetCCsForApproval(currentStaff);

            //Construct Lists for Notification menu
            viewORList = ConstructORequestListForNotification(orderRequests);
            List<Models.ViewTenders> tenders = ConstructTAListForNotification(tenderAnalyses);
            List<Models.ViewPOs> viewPOList = ConstructPOListForNotification(purchaseOrders);
            List<Models.ViewR4Payment> viewRFPList = ConstructRFPListForNotification(paymentRequests);
            List<Models.AdvanceRequestModel> viewRFAList = ConstructRFAListForNotification(advanceRequests);
            List<Models.ViewWRNs> viewWRNLists = ConstructWRNListForNotification(warehouseReleases);
            List<Models.ViewExpsClaims> viewECFList = ConstructECFListForNotification(expenseClaims);
            List<Models.ViewSalaryPayment> viewSPMList = ConstructSPMListForNotification(salaryRequests);
            List<Models.GRNote> viewGRNList = ConstructGRNListForNotification(goodsReceivedNotes);
            List<Models.ViewTAForms> viewTAFList = ConstructTAFListForNotification(travelAuthorizations);
            List<Models.PPModel> viewPPList = ConstructPPListForNotification(procurementPlans);
            List<Models.CompletionCtificate> viewCCList = ConstructCCListForNotification(completionCertificates);

            rrModel.OrderRequests = viewORList;
            rrModel.TenderAnalyses = tenders;
            rrModel.PurchaseOrders = viewPOList;
            rrModel.PaymentRequests = viewRFPList;
            rrModel.AdvanceRequests = viewRFAList;
            rrModel.WarehouseReleases = viewWRNLists;
            rrModel.ExpenseClaims = viewECFList;
            rrModel.SalaryPayments = viewSPMList;
            rrModel.GoodsReceivedNotes = viewGRNList;
            rrModel.TravelAuthorizations = viewTAFList;
            rrModel.ProcurementPlans = viewPPList;
            rrModel.CompletionCertificates = viewCCList;

            //REQUESTS FOR AUTHORIZATION
            orderRequests = orderRequestService.GetOrderRequestsForAuth(currentUser);
            purchaseOrders = purchaseOrderService.GetPurchaseOrdersForAuth(currentUser);
            tenderAnalyses = tAnalysisService.GetTenderAnalysesForAuth(currentUser);
            paymentRequests = request4PaymentService.GetPaymentRequests4Authorization(currentUser);
            advanceRequests = rfaService.GetAdvanceRequestsForAuth(currentUser);
            expenseClaims = expenseClaimService.GetExpenseClaimsForAuth(currentUser);
            salaryRequests = salaryPaymentService.GetSalaryPaymentsForAuth(currentUser);
            travelAuthorizations = tafService.GetTravelAuthorizationsForAuth(currentUser);

            viewORList = ConstructORequestListForNotification(orderRequests);
            tenders = ConstructTAListForNotification(tenderAnalyses);
            viewPOList = ConstructPOListForNotification(purchaseOrders);
            viewRFPList = ConstructRFPListForNotification(paymentRequests);
            viewRFAList = ConstructRFAListForNotification(advanceRequests);
            viewWRNLists = ConstructWRNListForNotification(warehouseReleases);
            viewECFList = ConstructECFListForNotification(expenseClaims);
            viewSPMList = ConstructSPMListForNotification(salaryRequests);
            viewTAFList = ConstructTAFListForNotification(travelAuthorizations);

            rrModel.AuthOrderRequests = viewORList;
            rrModel.AuthTenderAnalyses = tenders;
            rrModel.AuthPurchaseOrders = viewPOList;
            rrModel.AuthPaymentRequests = viewRFPList;
            rrModel.AuthAdvanceRequests = viewRFAList;
            rrModel.AuthWarehouseReleases = viewWRNLists;
            rrModel.AuthExpenseClaims = viewECFList;
            rrModel.AuthSalaryPayments = viewSPMList;
            rrModel.AuthTravelAuthorizations = viewTAFList;

            return View("ProcurementRequestLinks", rrModel);

        }

        public ActionResult GetRequestsForAuth()
        {
            List<Model.OrderRequest> orderRequests = orderRequestService.GetOrderRequestsForAuth(userContext.CurrentUser);
            List<Model.PurchaseOrder> purchaseOrders = purchaseOrderService.GetPurchaseOrdersForAuth(userContext.CurrentUser);
            List<Model.TenderAnalysi> tenderAnalyses = tAnalysisService.GetTenderColl((Guid)userContext.CurrentUser.Staff.CountrySubOffice.CountryProgrammeId);
            List<Models.ViewOR> viewORList = ConstructORequestListForNotification(orderRequests);
            List<Models.ViewTenders> tenders = new List<Models.ViewTenders>();
            List<Models.ViewPOs> viewPOList = ConstructPOListForNotification(purchaseOrders);
            Models.RequestReviewModel rrModel = new Models.RequestReviewModel();
            rrModel.OrderRequests = viewORList;
            rrModel.TenderAnalyses = tenders;
            rrModel.PurchaseOrders = viewPOList;
            //rrModel.PurchaseOrders
            ViewBag.IsReview = false;
            return View("ProcurementRequestLinks", rrModel);
        }

        private List<Models.ViewOR> ConstructORequestListForNotification(List<Model.OrderRequest> orList)
        {
            Models.ViewOR viewOR;
            List<Models.ViewOR> viewORList = new List<Models.ViewOR>();
            foreach (var or in orList)
            {
                viewOR = new Models.ViewOR();
                viewOR.EntityOR = or;
                viewOR.IssueDate = or.OrderDate.Value;
                viewOR.RequestDate = or.DeliveryDate.Value;
                viewOR.FirstItem = or.OrderRequestItems.Count > 0 ? or.OrderRequestItems.ToList()[0].Item.Name : "";
                viewOR.ProjNo = or.OrderRequestItems.Count > 0 ? or.OrderRequestItems.ToList()[0].ProjectBudget.BudgetCategory.ProjectDonor.ProjectNumber : "";
                viewOR.ProjName = or.OrderRequestItems.Count > 0 ? or.OrderRequestItems.ToList()[0].ProjectBudget.BudgetCategory.ProjectDonor.Project.Name : "";
                viewORList.Add(viewOR);
            }
            return viewORList;
        }

        private List<Models.ViewTenders> ConstructTAListForNotification(List<Model.TenderAnalysi> taList)
        {
            Models.ViewTenders viewTA;
            List<Models.ViewTenders> viewTAList = new List<Models.ViewTenders>();
            foreach (var ta in taList)
            {
                viewTA = new Models.ViewTenders();
                viewTA.EntityTenderAnalysis = ta;
                viewTAList.Add(viewTA);
            }
            return viewTAList;
        }

        private List<Models.ViewPOs> ConstructPOListForNotification(List<Model.PurchaseOrder> poList)
        {
            Models.ViewPOs viewPO;
            List<Models.ViewPOs> viewPOList = new List<Models.ViewPOs>();
            foreach (var po in poList)
            {
                viewPO = new Models.ViewPOs();
                viewPO.POEntiy = po;
                viewPOList.Add(viewPO);
            }
            return viewPOList;
        }

        private List<Models.ViewR4Payment> ConstructRFPListForNotification(List<Model.PaymentRequest> rfpList)
        {
            Models.ViewR4Payment viewRFP;
            List<Models.ViewR4Payment> viewRFPList = new List<Models.ViewR4Payment>();
            foreach (var rfp in rfpList)
            {
                viewRFP = new Models.ViewR4Payment();
                viewRFP.EntityPaymentRqst = rfp;
                viewRFPList.Add(viewRFP);
            }
            return viewRFPList;
        }

        private List<Models.AdvanceRequestModel> ConstructRFAListForNotification(List<AdvanceRequest> rfaList)
        {
            List<Models.AdvanceRequestModel> viewRFAList = new List<Models.AdvanceRequestModel>();
            foreach (AdvanceRequest item in rfaList)
            {
                viewRFAList.Add(Models.AdvanceRequestExtension.ToModel(item));
            }
            return viewRFAList;
        }

        private List<Models.ViewWRNs> ConstructWRNListForNotification(List<WarehouseRelease> wrnList)
        {
            List<Models.ViewWRNs> viewWRNList = new List<Models.ViewWRNs>();
            foreach (WarehouseRelease wrn in wrnList)
            {
                viewWRNList.Add(new Models.ViewWRNs { EntityWHouseRelease = wrn });
            }
            return viewWRNList;
        }

        private List<Models.ViewExpsClaims> ConstructECFListForNotification(List<ExpenseRequest> ecfList)
        {
            List<Models.ViewExpsClaims> viewECFList = new List<Models.ViewExpsClaims>();
            foreach (ExpenseRequest ecf in ecfList)
            {
                viewECFList.Add(new Models.ViewExpsClaims { EntityExpseRqst = ecf });
            }
            return viewECFList;
        }

        private List<Models.ViewSalaryPayment> ConstructSPMListForNotification(List<SalaryRequest> spmList)
        {
            List<Models.ViewSalaryPayment> viewSPMList = new List<Models.ViewSalaryPayment>();
            foreach (SalaryRequest spm in spmList)
            {
                viewSPMList.Add(new Models.ViewSalaryPayment { EntitySalaryP = spm });
            }
            return viewSPMList;
        }

        private List<Models.GRNote> ConstructGRNListForNotification(List<GoodsReceivedNote> grnList)
        {
            List<Models.GRNote> viewGRNList = new List<Models.GRNote>();
            foreach (GoodsReceivedNote grn in grnList)
            {
                viewGRNList.Add(new Models.GRNote { EntityGRN = grn });
            }
            return viewGRNList;
        }

        private List<Models.ViewTAForms> ConstructTAFListForNotification(List<TravelAuthorization> tafList)
        {
            List<Models.ViewTAForms> viewTAFList = new List<Models.ViewTAForms>();
            foreach (TravelAuthorization taf in tafList)
            {
                viewTAFList.Add(new Models.ViewTAForms { TAuthFormEntity = taf });
            }
            return viewTAFList;
        }

        private List<PPModel> ConstructPPListForNotification(List<ProcurementPlan> ppList)
        {
            List<PPModel> viewPPList = new List<PPModel>();
            foreach (var pp in ppList)
            {
                viewPPList.Add(new PPModel { EntityPP = pp });
            }
            return viewPPList;
        }

        private List<CompletionCtificate> ConstructCCListForNotification(List<CompletionCertificate> ccList)
        {
            List<CompletionCtificate> viewCCList = new List<CompletionCtificate>();
            foreach (var cc in ccList)
            {
                viewCCList.Add(new CompletionCtificate { EntityCC = cc });
            }
            return viewCCList;
        }

        #endregion

        #region .Order Request.

        public ActionResult LoadOrderRequestForApproval(Guid id, List<BudgetCheckResult> brcList = null)
        {

            Model.OrderRequest orderRequest = orderRequestService.GetOrderRequestById(id);
            Models.ReviewOR reviewOR = new Models.ReviewOR();
            List<Currency> currencies = orderRequestService.GetCurrencies(countryProg.Id);
            Models.ORequester oRequest = new Models.ORequester()
            {
                EntityOrderRequest = orderRequest,
                currencies = new SelectList(currencies, "Id", "ShortName", orderRequest.CurrencyId),

                Projects = new SelectList(orderRequestService.GetProject(countryProg.Id), "Id", "Name", orderRequest.ProjectId),
                ProjectNos = new SelectList(orderRequestService.GetProjectNos(countryProg.Id), "Id", "ProjectNumber", orderRequest.ProjectDonorId),
                RequestDelivLocations = new SelectList(orderRequestService.GetLocations(countryProg.Id), "Id", "Name"),
                FinalDelivLocations = new SelectList(orderRequestService.GetLocations(countryProg.Id), "Id", "Name"),
                OrderRequestNo = orderRequest.RefNumber,
                IssueDate = (DateTime)orderRequest.OrderDate,
                RequestDate = (DateTime)orderRequest.DeliveryDate
            };
            reviewOR.ORequest = oRequest;
            reviewOR.ProjectId = orderRequest.ProjectId;
            reviewOR.ProjectDonorId = orderRequest.ProjectDonorId;
            reviewOR.ORItems = ConstructOrderItemsList(orderRequest);
            reviewOR.IsFinanceReview = false;
            reviewOR.Currencies = new SelectList(currencies, "Id", "ShortName", reviewOR.MBCurrencyId);
            reviewOR.BudgetCheckResults = brcList;
            return View("EditOrderRequest", reviewOR);
        }

        public ActionResult LoadOrderRequest(Guid id, List<BudgetCheckResult> brcList = null)
        {

            Model.OrderRequest orderRequest = orderRequestService.GetOrderRequestById(id);
            Models.ReviewOR reviewOR = new Models.ReviewOR();
            List<Currency> currencies = orderRequestService.GetCurrencies(countryProg.Id);
            Models.ORequester oRequest = new Models.ORequester()
            {
                EntityOrderRequest = orderRequest,
                currencies = new SelectList(currencies, "Id", "ShortName", orderRequest.CurrencyId),

                Projects = new SelectList(orderRequestService.GetProject(countryProg.Id), "Id", "Name", orderRequest.ProjectId),
                ProjectNos = new SelectList(orderRequestService.GetProjectNos(countryProg.Id), "Id", "ProjectNumber", orderRequest.ProjectDonorId),
                RequestDelivLocations = new SelectList(orderRequestService.GetLocations(countryProg.Id), "Id", "Name"),
                FinalDelivLocations = new SelectList(orderRequestService.GetLocations(countryProg.Id), "Id", "Name"),
                OrderRequestNo = orderRequest.RefNumber,
                IssueDate = (DateTime)orderRequest.OrderDate,
                RequestDate = (DateTime)orderRequest.DeliveryDate
            };
            reviewOR.ORequest = oRequest;
            reviewOR.ProjectId = orderRequest.ProjectId;
            reviewOR.ProjectDonorId = orderRequest.ProjectDonorId;
            reviewOR.ORItems = ConstructOrderItemsList(orderRequest);
            reviewOR.MbValue = oRequest.EntityOrderRequest.MBValue;
            reviewOR.IsFinanceReview = true;
            if (oRequest.EntityOrderRequest.MBCurrencyId != null)
                reviewOR.MBCurrencyId = oRequest.EntityOrderRequest.MBCurrencyId.ToString();
            else
                reviewOR.MBCurrencyId = countryProg.Currency.Id.ToString();
            reviewOR.Currencies = new SelectList(currencies, "Id", "ShortName", reviewOR.MBCurrencyId);
            reviewOR.BudgetCheckResults = brcList;
            return View("EditOrderRequest", reviewOR);
        }

        public ActionResult LoadOrderRequestForAuth(Guid id, List<BudgetCheckResult> brcList = null)
        {

            Model.OrderRequest orderRequest = orderRequestService.GetOrderRequestById(id);
            Models.ReviewOR reviewOR = new Models.ReviewOR();
            List<Currency> currencies = orderRequestService.GetCurrencies(countryProg.Id);
            Models.ORequester oRequest = new Models.ORequester()
            {
                EntityOrderRequest = orderRequest,
                currencies = new SelectList(currencies, "Id", "ShortName", orderRequest.CurrencyId),
                Projects = new SelectList(orderRequestService.GetProject(countryProg.Id), "Id", "Name", orderRequest.ProjectId),
                ProjectNos = new SelectList(orderRequestService.GetProjectNos(countryProg.Id), "Id", "ProjectNumber", orderRequest.ProjectDonorId),
                RequestDelivLocations = new SelectList(orderRequestService.GetLocations(countryProg.Id), "Id", "Name"),
                FinalDelivLocations = new SelectList(orderRequestService.GetLocations(countryProg.Id), "Id", "Name"),
                OrderRequestNo = orderRequest.RefNumber, //this.GenerateUniqueCode(),
                IssueDate = (DateTime)orderRequest.OrderDate,
                RequestDate = (DateTime)orderRequest.DeliveryDate,
            };
            reviewOR.ORequest = oRequest;
            reviewOR.ProjectId = orderRequest.ProjectId;
            reviewOR.ProjectDonorId = orderRequest.ProjectDonorId;
            reviewOR.ORItems = ConstructOrderItemsList(orderRequest);
            reviewOR.MbValue = oRequest.EntityOrderRequest.MBValue;
            reviewOR.MBCurrencyId = oRequest.EntityOrderRequest.MBCurrencyId.ToString();
            reviewOR.Currencies = new SelectList(currencies, "Id", "ShortName", reviewOR.MBCurrencyId);
            reviewOR.BudgetCheckResults = brcList;
            return View("AuthorizeOR", reviewOR);

        }

        private List<Models.ReviewOrderRequestItem> ConstructOrderItemsList(Model.OrderRequest orderRequest)
        {
            List<Model.OrderRequestItem> orItemList = orderRequestService.GetOrderRequestItems(orderRequest.Id);
            List<Models.ReviewOrderRequestItem> orDetailsList = new List<Models.ReviewOrderRequestItem>();
            Models.ReviewOrderRequestItem orDetail;
            List<ProjectDonor> pdList = orderRequestService.GetProjectNos(countryProg.Id);
            List<BudgetLineView> budgetLines = orderRequestService.GetProjectBugdetLines((Guid)orderRequest.ProjectDonorId);

            foreach (Model.OrderRequestItem orItem in orItemList)
            {
                orDetail = new Models.ReviewOrderRequestItem();
                orDetail.EntityOrderRequestItem = orItem;
                orDetail.Description = orItem.ItemDescription;
                orDetail.BudgetLineID = orItem.BudgetLineId.ToString();
                orDetail.OrderRequestItemId = orItem.Id;
                orDetail.ProjectNoID = orItem.OrderRequest.ProjectDonorId.ToString();
                orDetail.Quantity = orItem.Quantity;
                orDetail.UnitMessureID = orItem.Item.UnitOfMeasure.Id.ToString();
                orDetail.UnitPrice = orItem.EstimatedUnitPrice;
                orDetail.TotalPrice = orItem.EstimatedPrice;
                orDetail.Remarks = orItem.Remarks;
                orDetail.ProjectNos = new SelectList(pdList, "Id", "ProjectNumber", orItem.OrderRequest.ProjectDonorId);
                orDetail.BudgetLines = new SelectList(budgetLines, "Id", "Description", orItem.BudgetLineId);
                orDetail.UnitMessures = new SelectList(orderRequestService.GetUnitMesures(countryProg.Id), "Id", "Code", orItem.Item.UnitOfMeasure);
                orDetailsList.Add(orDetail);
            }
            return orDetailsList;
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ApproveOrder(Models.ReviewOR reviewOR)
        {

            Model.OrderRequestItem entityOrItem;
            Model.OrderRequest entityOR = orderRequestService.GetOrderRequestById(reviewOR.ORequest.EntityOrderRequest.Id);
            entityOR.TotalAmount = 0;
            if (reviewOR.ORItems != null)
            {
                foreach (Models.ReviewOrderRequestItem orItem in reviewOR.ORItems)
                {
                    entityOrItem = orderRequestService.GetOrderRequestItemById(orItem.OrderRequestItemId);
                    if (entityOrItem == null)
                        continue;
                    entityOrItem.Quantity = orItem.Quantity;
                    entityOrItem.EstimatedUnitPrice = orItem.UnitPrice;
                    entityOrItem.EstimatedPrice = (orItem.Quantity * orItem.UnitPrice);
                    //Add to the TotalAmount of the Order
                    entityOR.TotalAmount += entityOrItem.EstimatedPrice;
                    entityOrItem.BudgetLineId = new Guid(orItem.BudgetLineID);
                    orderRequestService.EditOrderRequestItem(entityOrItem);
                }
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = orderRequestService.RunFundsAvailableCheck(reviewOR.ORequest.EntityOrderRequest.Id);
            if (bcrList.Count > 0)
                return LoadOrderRequestForApproval(reviewOR.ORequest.EntityOrderRequest.Id, bcrList);

            entityOR.ApprovedBy = currentStaff.Id;
            entityOR.ApprovedOn = DateTime.Now;
            entityOR.IsApproved = true;
            orderRequestService.UpdateOrderRequest(entityOR);
            //Notifiy Finance Reviewer
            notificationService.SendToAppropriateApprover(NotificationHelper.orCode, NotificationHelper.reviewCode, entityOR.Id);
            //orderRequestService.NotifiyAuthorizer(entityOR);
            //Notify requestor
            string msgBody = string.Format(NotificationHelper.orApprovedMsgBody, entityOR.Staff2.Person.FirstName, entityOR.RefNumber);
            notificationService.SendNotification(entityOR.Staff2.Person.OfficialEmail, msgBody, NotificationHelper.orsubject);
            return GetRequests();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ReviewOrder(Models.ReviewOR reviewOR)
        {

            Model.OrderRequestItem entityOrItem;
            Model.OrderRequest entityOR = orderRequestService.GetOrderRequestById(reviewOR.ORequest.EntityOrderRequest.Id);
            entityOR.MBCurrencyId = new Guid(reviewOR.MBCurrencyId);
            entityOR.MBValue = reviewOR.MbValue;
            entityOR.TotalAmount = 0;
            if (reviewOR.ORItems != null)
            {
                foreach (Models.ReviewOrderRequestItem orItem in reviewOR.ORItems)
                {
                    entityOrItem = orderRequestService.GetOrderRequestItemById(orItem.OrderRequestItemId);
                    if (entityOrItem == null)
                        continue;
                    entityOrItem.Quantity = orItem.Quantity;
                    entityOrItem.EstimatedUnitPrice = orItem.UnitPrice;
                    entityOrItem.EstimatedPrice = (orItem.Quantity * orItem.UnitPrice);
                    //Add to the TotalAmount of the Order
                    entityOR.TotalAmount += entityOrItem.EstimatedPrice;
                    entityOrItem.BudgetLineId = new Guid(orItem.BudgetLineID);
                    orderRequestService.EditOrderRequestItem(entityOrItem);
                }
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = orderRequestService.RunFundsAvailableCheck(reviewOR.ORequest.EntityOrderRequest.Id);
            if (bcrList.Count > 0)
                return LoadOrderRequest(reviewOR.ORequest.EntityOrderRequest.Id, bcrList);

            entityOR.ReviewedBy = currentStaff.Id;
            entityOR.ReviewedOn = DateTime.Now;
            entityOR.IsReviewed = true;
            orderRequestService.UpdateOrderRequest(entityOR);
            //Notifiy authorizer
            notificationService.SendToAppropriateApprover(NotificationHelper.orCode, NotificationHelper.authorizationCode, entityOR.Id);
            //orderRequestService.NotifiyAuthorizer(entityOR);
            //Notify requestor
            string msgBody = string.Format(NotificationHelper.orMsgReviewedBody, entityOR.Staff2.Person.FirstName, entityOR.RefNumber);
            notificationService.SendNotification(entityOR.Staff2.Person.OfficialEmail, msgBody, NotificationHelper.orsubject);
            return GetRequests();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult AuthorizeOrder(Models.ReviewOR reviewOR)
        {

            Model.OrderRequestItem entityOrItem;
            Model.OrderRequest entityOR = orderRequestService.GetOrderRequestById(reviewOR.ORequest.EntityOrderRequest.Id);
            entityOR.MBValue = reviewOR.MbValue;
            entityOR.Remarks = reviewOR.ORequest.EntityOrderRequest.Remarks;
            entityOR.TotalAmount = 0;
            if (reviewOR.ORItems != null)
            {
                foreach (Models.ReviewOrderRequestItem orItem in reviewOR.ORItems)
                {
                    entityOrItem = orderRequestService.GetOrderRequestItemById(orItem.OrderRequestItemId);
                    if (entityOrItem == null)
                        continue;
                    //entityOrItem.UnitOfMeasure = new Guid(orItem.UnitMessureID);
                    entityOrItem.Quantity = orItem.Quantity;
                    entityOrItem.EstimatedUnitPrice = orItem.UnitPrice;
                    entityOrItem.EstimatedPrice = (orItem.Quantity * orItem.UnitPrice);
                    //Add to the TotalAmount of the Order
                    entityOR.TotalAmount += entityOrItem.EstimatedPrice;
                    entityOrItem.BudgetLineId = new Guid(orItem.BudgetLineID);
                    orderRequestService.EditOrderRequestItem(entityOrItem);
                }
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = orderRequestService.RunFundsAvailableCheck(reviewOR.ORequest.EntityOrderRequest.Id);
            if (bcrList.Count > 0)
                return LoadOrderRequestForAuth(reviewOR.ORequest.EntityOrderRequest.Id, bcrList);

            entityOR.AuthorizedBy = userContext.CurrentUser.StaffId;
            entityOR.AuthorizedOn = DateTime.Now;
            entityOR.IsAuthorized = true;
            orderRequestService.UpdateOrderRequest(entityOR);
            orderRequestService.AuthorizeOrderRequest(entityOR);
            //Notify requestor
            string msgBody = string.Format(NotificationHelper.orAuthorizedMsgBody, entityOR.Staff2.Person.FirstName, entityOR.RefNumber);
            notificationService.SendNotification(entityOR.Staff2.Person.OfficialEmail, msgBody, NotificationHelper.orsubject);
            //Notify Project Manager
            notificationService.SendAuthorizedMsgToPMs(NotificationHelper.orCode, entityOR.Id);
            //Notify TA Prep In charge
            notificationService.SendAuthorizedMsgToDocPreparers(NotificationHelper.orCode, entityOR.Id);

            ViewBag.Message = string.Format(Resources.RequestReviewController_String_HasBeenAuthorized, entityOR.RefNumber);
            ViewBag.PdfURL = "/Reports/OrderRequest/pdf?orId=" + entityOR.Id;
            return View("AuthComplete");
        }

        public ActionResult LoadRejectOrder(Guid Id)
        {
            Models.RejectOR model = new Models.RejectOR();
            Model.OrderRequest entityOR = orderRequestService.GetOrderRequestById(Id);
            model.Id = entityOR.Id;
            model.RefNumber = entityOR.RefNumber;
            if (entityOR.IsReviewed == true)
            {
                model.IsReview = false;
                model.RejectedReviewRemarks = Resources.Global_String_None;
            }
            else
            {
                model.IsReview = true;
                model.RejectedAuthRemarks = Resources.Global_String_None;
            }
            return View("RejectOR", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult RejectOrder(Models.RejectOR rejectedOR)
        {
            string notificationMsg;
            Model.OrderRequest entityOR = orderRequestService.GetOrderRequestById(rejectedOR.Id);
            entityOR.IsRejected = true;
            if (rejectedOR.IsReview)
            {
                entityOR.RejectedReviewRemarks = rejectedOR.RejectedReviewRemarks;
                entityOR.ReviewedBy = currentStaff.Id;
                entityOR.ReviewedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.orRejectedMsgBody, entityOR.Staff2.Person.FirstName, entityOR.RefNumber, entityOR.RejectedReviewRemarks);
            }
            else
            {
                entityOR.RejectedAuthorizeRemarks = rejectedOR.RejectedAuthRemarks;
                entityOR.AuthorizedBy = currentStaff.Id;
                entityOR.AuthorizedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.orRejectedMsgBody, entityOR.Staff2.Person.FirstName, entityOR.RefNumber, entityOR.RejectedAuthorizeRemarks);
            }
            orderRequestService.UpdateOrderRequest(entityOR);
                        
            //Notify Project Manager
            notificationService.SendRejectedMsgToPMs(NotificationHelper.orCode, entityOR.Id, notificationMsg);
            //Notify Approver if approver is not the one logged in
            if (entityOR.Staff != null && entityOR.Staff.Id != currentStaff.Id)
            {
                notificationService.SendNotification(entityOR.Staff.Person.OfficialEmail, notificationMsg, NotificationHelper.orsubject);
            }
            else if (entityOR.Staff == null)
            {
                //Notify Requestor
                notificationService.SendNotification(entityOR.Staff2.Person.OfficialEmail, notificationMsg, NotificationHelper.orsubject);
            }

            return LoadRejectOrder(rejectedOR.Id);
        }

        #endregion

        #region .Tender Analysis.

        public ActionResult ReviewTA(Guid Id)
        {

            Models.TenderAnalysis modelTA = new Models.TenderAnalysis();
            modelTA.TenderAnalysisId = Id;
            modelTA.HasSuppliers = false;
            List<TenderBidder> TBList = tAnalysisService.GetTenderBidderColl(Id);
            List<Models.TenderItem> tenderItems = new List<Models.TenderItem>();
            modelTA.EntityTenderAnalysis = tAnalysisService.GetTenderAnalysisEntity(Id);
            Models.TenderItem tenderItem;
            List<TenderBidderQuote> tbQuotes;
            PopulateTALists(modelTA, TBList);
            if (TBList.Count > 0)
            {
                modelTA.HasSuppliers = true;
                tbQuotes = tAnalysisService.GetTenderBidderQuoteColl(TBList[0].Id);
                foreach (TenderBidderQuote tbQuote in tbQuotes)
                {
                    tenderItem = new Models.TenderItem();
                    tenderItem.UnitCost = new List<decimal>();
                    tenderItem.EntityRequestedItem = tbQuote.OrderRequestItem;
                    tenderItem.UnitCost.Add(tbQuote.UnitPrice);
                    tenderItems.Add(tenderItem);
                }
            }

            for (int i = 1; i < TBList.Count; i++)
            {
                tbQuotes = tAnalysisService.GetTenderBidderQuoteColl(TBList[i].Id);
                for (int j = 0; j < tbQuotes.Count; j++)
                {
                    tenderItems[j].UnitCost.Add(tbQuotes[j].UnitPrice);
                }
            }
            ViewBag.Currency = modelTA.EntityTenderAnalysis.OrderRequest.Currency.ShortName;
            modelTA.TBiderQuotes = tenderItems;
            modelTA.Suppliers = new SelectList(tAnalysisService.GetTenderBidderSuppliers(modelTA.EntityTenderAnalysis.Id), "Id", "Name");
            return View("ReviewTA", modelTA);

        }

        private void PopulateTALists(SCMS.UI.Models.TenderAnalysis ta, List<TenderBidder> tbList)
        {
            ta.SupplierName = new List<string>();
            ta.SupplierID = new List<Guid>();
            ta.ShippingTerm = new List<string>();
            ta.TermzOfPayment = new List<string>();
            ta.Warrant = new List<string>();
            ta.DeliveryTime = new List<DateTime>();
            ta.others = new List<string>();
            ta.TransportCost = new List<decimal>();
            ta.OtherID = new List<Guid>();
            ta.TotalCost = new List<decimal>();

            foreach (TenderBidder tb in tbList)
            {

                ta.SupplierName.Add(tb.Supplier.Name);
                ta.SupplierID.Add(tb.SupplierId);
                if (tb.ShippingTermId != null)
                    ta.ShippingTerm.Add(tb.ShippingTerm.Name);
                if (tb.PaymentTermId != null)
                    ta.TermzOfPayment.Add(tb.PaymentTerm.Code);
                if (tb.Warranty != null)
                    ta.Warrant.Add(tb.Warranty);
                if (tb.DeliveryTime != null)
                    ta.DeliveryTime.Add((DateTime)tb.DeliveryTime);
                if (tb.Comments != null)
                    ta.others.Add(tb.Comments);
                if (tb.TransportCost != null)
                    ta.TransportCost.Add((decimal)tb.TransportCost);
                ta.OtherID.Add(tb.Id);
                ta.TotalCost.Add((decimal)tb.TotalCost);
            }
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult EvaluateTA(Models.TenderAnalysis modelTA)
        {

            Model.TenderAnalysi ta = tAnalysisService.GetTenderAnalysisEntity(modelTA.EntityTenderAnalysis.Id);
            List<TenderEvaluator> evaluators = tAnalysisService.GetTenderEvaluators(ta.Id);
            int evalLevel = 0;
            foreach (var evaluator in evaluators)
            {
                if (evaluator.StaffId == currentStaff.Id)
                {
                    evaluator.Remarks = modelTA.Remarks;
                    evaluator.RecommendedSupplierId = modelTA.RecommendedSupplierId;
                    evaluator.DateApproved = DateTime.Now;
                    evaluator.HasApproved = true;
                    tAnalysisService.SaveEvaluators(evaluator);
                    evalLevel = (int)evaluator.Priority;
                    break;
                }
            }
            if (evalLevel == 1)
            {
                foreach (var evaluator in evaluators)
                {
                    if (evaluator.Priority == 2)
                    {
                        notificationService.SendNotification(evaluator.Staff.Person.OfficialEmail, string.Format(NotificationHelper.taMsgBody, evaluator.Staff.Person.FirstName), NotificationHelper.tasubject);
                        break;
                    }
                }
            }
            else if (evalLevel == 2)
            {
                foreach (var evaluator in evaluators)
                {
                    if (evaluator.Priority == 3)
                    {
                        notificationService.SendNotification(evaluator.Staff.Person.OfficialEmail, string.Format(NotificationHelper.taAuthMsgBody, evaluator.Staff.Person.FirstName, ta.RefNumber), NotificationHelper.tasubject);
                        break;
                    }
                }
            }
            //Response.Redirect("/TenderAnalysis/ViewTenderDetails/" + modelTA.EntityTenderAnalysis.Id);
            return ReviewTA(ta.Id);

        }

        public ActionResult RejectTA(Guid Id)
        {
            Model.TenderAnalysi ta = tAnalysisService.GetTenderAnalysisEntity(Id);
            List<TenderEvaluator> evaluators = tAnalysisService.GetTenderEvaluators(ta.Id);
            int evalLevel = 0;
            foreach (TenderEvaluator evaluator in evaluators)
            {
                if (evaluator.StaffId == currentStaff.Id)
                {
                    evaluator.DateApproved = DateTime.Now;
                    evaluator.HasApproved = false;
                    tAnalysisService.SaveEvaluators(evaluator);
                    evalLevel = (int)evaluator.Priority;
                    break;
                }
            }
            if (evalLevel == 1)
            {
                foreach (var evaluator in evaluators)
                {
                    if (evaluator.Priority == 2)
                    {
                        notificationService.SendNotification(evaluator.Staff.Person.OfficialEmail, string.Format(NotificationHelper.taMsgBody, evaluator.Staff.Person.FirstName), NotificationHelper.tasubject);
                        break;
                    }
                }
            }
            else if (evalLevel == 2)
            {
                foreach (var evaluator in evaluators)
                {
                    if (evaluator.Priority == 3)
                    {
                        notificationService.SendNotification(evaluator.Staff.Person.OfficialEmail, string.Format(NotificationHelper.taAuthMsgBody, evaluator.Staff.Person.FirstName, ta.RefNumber), NotificationHelper.tasubject);
                        break;
                    }
                }
            }
            return ReviewTA(Id);
        }

        public ActionResult LoadTAForAuth(Guid Id)
        {

            Models.TenderAnalysis modelTA = new Models.TenderAnalysis();
            modelTA.TenderAnalysisId = Id;
            modelTA.HasSuppliers = false;
            List<TenderBidder> TBList = tAnalysisService.GetTenderBidderColl(Id);
            List<Models.TenderItem> tenderItems = new List<Models.TenderItem>();
            modelTA.EntityTenderAnalysis = tAnalysisService.GetTenderAnalysisEntity(Id);
            modelTA.TenderEvaluators = tAnalysisService.GetTenderEvaluators(Id);
            Models.TenderItem tenderItem;
            List<TenderBidderQuote> tbQuotes;
            PopulateTALists(modelTA, TBList);
            if (TBList.Count > 0)
            {
                modelTA.HasSuppliers = true;
                tbQuotes = tAnalysisService.GetTenderBidderQuoteColl(TBList[0].Id);
                foreach (TenderBidderQuote tbQuote in tbQuotes)
                {
                    tenderItem = new Models.TenderItem();
                    tenderItem.UnitCost = new List<decimal>();
                    tenderItem.EntityRequestedItem = tbQuote.OrderRequestItem;
                    tenderItem.UnitCost.Add(tbQuote.UnitPrice);
                    tenderItems.Add(tenderItem);
                }
            }

            for (int i = 1; i < TBList.Count; i++)
            {
                tbQuotes = tAnalysisService.GetTenderBidderQuoteColl(TBList[i].Id);
                for (int j = 0; j < tbQuotes.Count; j++)
                {
                    tenderItems[j].UnitCost.Add(tbQuotes[j].UnitPrice);
                }
            }
            ViewBag.Currency = modelTA.EntityTenderAnalysis.OrderRequest.Currency.ShortName;
            modelTA.TBiderQuotes = tenderItems;
            modelTA.Suppliers = new SelectList(tAnalysisService.GetTenderBidderSuppliers(modelTA.EntityTenderAnalysis.Id), "Id", "Name");
            return View("AuthorizeTA", modelTA);

        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult AuthorizeTA(Models.TenderAnalysis modelTA)
        {
            Model.TenderAnalysi ta = tAnalysisService.GetTenderAnalysisEntity(modelTA.EntityTenderAnalysis.Id);
            List<TenderEvaluator> evaluators = tAnalysisService.GetTenderEvaluators(ta.Id);
            foreach (var evaluator in evaluators)
            {
                if (evaluator.Priority == 3 && evaluator.StaffId == currentStaff.Id)
                {
                    evaluator.Remarks = modelTA.Remarks;
                    evaluator.RecommendedSupplierId = modelTA.RecommendedSupplierId;
                    evaluator.DateApproved = DateTime.Now;
                    evaluator.HasApproved = true;
                    tAnalysisService.SaveEvaluators(evaluator);
                    break;
                }
            }

            ta.SelectedSupplierId = modelTA.RecommendedSupplierId;
            ta.Recommendation = modelTA.Remarks;
            ta.SupplierSelected = true;
            ta.IsAuthorized = true;
            ta.AuthorizedBy = currentStaff.Id;
            ta.AuthorizedOn = DateTime.Now;
            tAnalysisService.AuthorizeTA(ta);

            notificationService.SendNotification(ta.Staff1.Person.OfficialEmail, string.Format(NotificationHelper.taAuthMsgBody, ta.Staff1.Person.FirstName, ta.RefNumber), NotificationHelper.tasubject);
            //Notify TA Prep In charge
            notificationService.SendAuthorizedMsgToDocPreparers(NotificationHelper.taCode, ta.Id);

            ViewBag.Message = string.Format(Resources.RequestReviewController_String_HasBeenAuthorized, ta.RefNumber);
            //ViewBag.PdfURL = "/Reports/TenderAnalysis/ViewTenderAnalysis/" + ta.Id;
            ViewBag.PdfURL = "/Reports/TA/Index?TAid=" + ta.Id;
            return View("AuthComplete");
        }

        public ActionResult LoadRejectTA(Guid Id)
        {
            Models.RejectTA model = new Models.RejectTA();
            TenderAnalysi entityTA = tAnalysisService.GetTenderAnalysisEntity(Id);
            model.Id = entityTA.Id;
            model.RefNumber = entityTA.RefNumber;
            return View("RejectTA", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult RejectTA(Models.RejectPO rejectedTA)
        {
            string notificationMsg;
            TenderAnalysi entityTA = tAnalysisService.GetTenderAnalysisEntity(rejectedTA.Id);
            entityTA.IsRejected = true;
            entityTA.RejectedAuthorizeRemarks = rejectedTA.RejectedAuthRemarks;
            entityTA.IsAuthorized = false;
            entityTA.AuthorizedBy = currentStaff.Id;
            entityTA.AuthorizedOn = DateTime.Now;
            notificationMsg = string.Format(NotificationHelper.taRejectedMsgBody, entityTA.Staff1.Person.FirstName, entityTA.RefNumber, entityTA.RejectedAuthorizeRemarks);
            tAnalysisService.SaveTenderAnalysis(entityTA);
            notificationService.SendNotification(entityTA.Staff1.Person.OfficialEmail, notificationMsg, NotificationHelper.tasubject);
            return LoadRejectTA(rejectedTA.Id);
        }

        #endregion

        #region .Purchase Order.

        public ActionResult LoadPurchaseOrder(Guid id, List<BudgetCheckResult> bcrList = null)
        {

            Model.PurchaseOrder po = purchaseOrderService.GetPurchaseOrderById(id);
            Models.ReviewPO reviewPO = new Models.ReviewPO();
            List<Currency> currencies = orderRequestService.GetCurrencies(countryProg.Id);
            Models.ViewPOs viewPO = new Models.ViewPOs()
            {
                POEntiy = po,
                shippingTerm = po.ShippingTerm.Name,
                paymentTerm = po.PaymentTerm.Description,
                supplier = po.Supplier.Name,
                deleliveryDate = (DateTime)po.LatestDeliveryDate,
                PODate = (DateTime)po.PreparedOn
            };
            reviewPO.ViewPO = viewPO;
            reviewPO.Currencies = new SelectList(currencies, "Id", "ShortName", userContext.CurrentUser.Staff.CountrySubOffice.CountryProgrammeId);
            reviewPO.POItems = ConstructPOItemsList(po);
            reviewPO.MbValue = viewPO.POEntiy.MBValue;
            reviewPO.MBCurrencyId = mbCurrency.Id.ToString();
            reviewPO.BudgetCheckResults = bcrList;
            return View("ReviewPO", reviewPO);

        }

        public ActionResult LoadPurchaseOrderForAuth(Guid id, List<BudgetCheckResult> bcrList)
        {

            Model.PurchaseOrder po = purchaseOrderService.GetPurchaseOrderById(id);
            Models.ReviewPO reviewPO = new Models.ReviewPO();
            List<Currency> currencies = orderRequestService.GetCurrencies(countryProg.Id);
            Models.ViewPOs viewPO = new Models.ViewPOs()
            {
                POEntiy = po,
                shippingTerm = po.ShippingTerm.Name,
                paymentTerm = po.PaymentTerm.Description,
                supplier = po.Supplier.Name
            };
            reviewPO.ViewPO = viewPO;
            reviewPO.POItems = ConstructPOItemsList(po);
            reviewPO.MbValue = viewPO.POEntiy.MBValue;
            reviewPO.MBCurrencyId = viewPO.POEntiy.MBCurrencyId.ToString();
            reviewPO.Currencies = new SelectList(currencies, "Id", "ShortName", reviewPO.MBCurrencyId);
            reviewPO.BudgetCheckResults = bcrList;
            return View("AuthorizePO", reviewPO);

        }

        private List<Models.ReviewPOItem> ConstructPOItemsList(Model.PurchaseOrder purchaseOrder)
        {

            List<Model.PurchaseOrderItem> poItemList = purchaseOrderService.GetPurchaseOrderItems(purchaseOrder.Id);
            List<Models.ReviewPOItem> poItems = new List<Models.ReviewPOItem>();
            Models.ReviewPOItem poItem;
            List<ProjectDonor> pdList = orderRequestService.GetProjectNos(countryProg.Id);
            List<BudgetLineView> budgetLines = new List<BudgetLineView>();
            ProjectBudget budgetLine;

            foreach (Model.PurchaseOrderItem item in poItemList)
            {
                poItem = new Models.ReviewPOItem();
                poItem.EntityPOItem = item;
                poItem.POItemId = item.Id;
                poItem.Quantity = item.Quantity;
                poItem.UnitCost = item.UnitPrice;
                poItem.TotalCost = item.TotalPrice;
                poItem.BudgetLineId = item.BudgetLineId;
                poItem.Remarks = item.Remarks;
                budgetLine = budgetService.GetProjectBudgetById(item.BudgetLineId.Value);
                budgetLines = orderRequestService.GetProjectBugdetLines(budgetLine.BudgetCategory.ProjectDonor.Id);
                poItem.BudgetLines = new SelectList(budgetLines, "Id", "Description", budgetLine.Id);
                poItem.UnitOfMeasure = item.OrderRequestItem != null ? item.OrderRequestItem.Item.UnitOfMeasure.Code : "N/A";
                poItems.Add(poItem);
            }
            return poItems;
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ApprovePO(Models.ReviewPO reviewPO)
        {
            Model.PurchaseOrderItem entityPOItem;
            Model.PurchaseOrder entityPO = purchaseOrderService.GetPurchaseOrderById(reviewPO.ViewPO.POEntiy.Id);
            entityPO.MBCurrencyId = new Guid(reviewPO.MBCurrencyId);
            entityPO.MBValue = reviewPO.MbValue;
            entityPO.TotalAmount = 0;
            if (reviewPO.POItems != null)
            {
                foreach (Models.ReviewPOItem poItem in reviewPO.POItems)
                {
                    entityPOItem = purchaseOrderService.GetPurchaseOrderItemById(poItem.POItemId);
                    if (entityPOItem == null)
                        continue;
                    entityPOItem.Quantity = poItem.Quantity;
                    entityPOItem.UnitPrice = poItem.UnitCost;
                    entityPOItem.TotalPrice = (decimal)(poItem.Quantity * poItem.UnitCost);
                    //Add to the TotalAmount of the Order
                    entityPO.TotalAmount += entityPOItem.TotalPrice;
                    entityPOItem.BudgetLineId = poItem.BudgetLineId;
                    purchaseOrderService.SaveReviewedPOItem(entityPOItem);
                }
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = purchaseOrderService.RunFundsAvailableCheck(reviewPO.ViewPO.POEntiy.Id);
            if (bcrList.Count > 0)
                return LoadPurchaseOrder(reviewPO.ViewPO.POEntiy.Id, bcrList);

            entityPO.ReviewedBy = currentStaff.Id;
            entityPO.ReviewedOn = DateTime.Now;
            entityPO.IsReviewed = true;
            purchaseOrderService.SaveReviewedPO(entityPO);
            //Notify Authorizer and PM
            notificationService.SendToAppropriateApprover(NotificationHelper.poCode, NotificationHelper.authorizationCode, entityPO.Id);
            //Send notification to sender that PO has been approved
            notificationService.SendNotification(entityPO.Staff1.Person.OfficialEmail, string.Format(NotificationHelper.poApprovedMsgBody, entityPO.Staff1.Person.FirstName, entityPO.RefNumber), NotificationHelper.posubject);
            return GetRequests();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult AuthorizePO(Models.ReviewPO reviewPO)
        {

            Model.PurchaseOrderItem entityPOItem;
            Model.PurchaseOrder entityPO = purchaseOrderService.GetPurchaseOrderById(reviewPO.ViewPO.POEntiy.Id);
            entityPO.MBValue = reviewPO.MbValue;
            entityPO.AdditionalRemarks = reviewPO.ViewPO.POEntiy.AdditionalRemarks;
            entityPO.TotalAmount = 0;
            if (reviewPO.POItems != null)
            {
                foreach (Models.ReviewPOItem poItem in reviewPO.POItems)
                {
                    entityPOItem = purchaseOrderService.GetPurchaseOrderItemById(poItem.POItemId);
                    if (entityPOItem == null)
                        continue;
                    entityPOItem.Quantity = poItem.Quantity;
                    entityPOItem.UnitPrice = poItem.UnitCost;
                    entityPOItem.TotalPrice = (decimal)(poItem.Quantity * poItem.UnitCost);
                    //Add to the TotalAmount of the Order
                    entityPO.TotalAmount += entityPOItem.TotalPrice;
                    entityPOItem.BudgetLineId = poItem.BudgetLineId;
                    purchaseOrderService.SaveReviewedPOItem(entityPOItem);
                }
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = purchaseOrderService.RunFundsAvailableCheck(reviewPO.ViewPO.POEntiy.Id);
            if (bcrList.Count > 0)
                return LoadPurchaseOrderForAuth(reviewPO.ViewPO.POEntiy.Id, bcrList);

            entityPO.AuthorizedBy = userContext.CurrentUser.StaffId;
            entityPO.AuthorizedOn = DateTime.Now;
            entityPO.IsAuthorized = true;
            purchaseOrderService.AuthorizePurchaseOrder(entityPO); 
            purchaseOrderService.SaveReviewedPO(entityPO);            
            //Notify Project Manager about authorized PO
            notificationService.SendAuthorizedMsgToPMs(NotificationHelper.poCode, entityPO.Id);
            //Send notification to sender that PO has been authorized
            notificationService.SendNotification(entityPO.Staff1.Person.OfficialEmail, string.Format(NotificationHelper.poAuthorizedMsgBody, entityPO.Staff1.Person.FirstName, entityPO.RefNumber), NotificationHelper.posubject);
            //Notify TA Prep In charge
            notificationService.SendAuthorizedMsgToDocPreparers(NotificationHelper.poCode, entityPO.Id);

            ViewBag.Message = string.Format(Resources.RequestReviewController_String_HasBeenAuthorized, entityPO.RefNumber);
            ViewBag.PdfURL = "/Reports/PO/Index?POid=" + entityPO.Id;
            return View("AuthComplete");
        }

        public ActionResult LoadRejectPO(Guid Id)
        {
            Models.RejectPO model = new Models.RejectPO();
            PurchaseOrder entityPO = purchaseOrderService.GetPurchaseOrderById(Id);
            model.Id = entityPO.Id;
            if (entityPO.IsReviewed == true)
            {
                model.IsReview = false;
                model.RejectedReviewRemarks = Resources.Global_String_None;
            }
            else
            {
                model.IsReview = true;
                model.RejectedAuthRemarks = Resources.Global_String_None;
            }
            return View("RejectPO", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult RejectPO(Models.RejectPO rejectedPO)
        {
            string notificationMsg;
            PurchaseOrder entityPO = purchaseOrderService.GetPurchaseOrderById(rejectedPO.Id);
            entityPO.IsRejected = true;
            if (rejectedPO.IsReview)
            {
                entityPO.RejectedReviewRemarks = rejectedPO.RejectedReviewRemarks;
                entityPO.ReviewedBy = currentStaff.Id;
                entityPO.ReviewedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.poRejectedMsgBody, entityPO.Staff1.Person.FirstName, entityPO.RefNumber, entityPO.RejectedReviewRemarks);
            }
            else
            {
                entityPO.RejectedAuthorizeRemarks = rejectedPO.RejectedAuthRemarks;
                entityPO.AuthorizedBy = currentStaff.Id;
                entityPO.AuthorizedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.poRejectedMsgBody, entityPO.Staff1.Person.FirstName, entityPO.RefNumber, entityPO.RejectedAuthorizeRemarks);
            }
            purchaseOrderService.SaveReviewedPO(entityPO);
            //Notify Project Manager(s)
            notificationService.SendRejectedMsgToPMs(NotificationHelper.poCode, entityPO.Id, notificationMsg);
            //Notify requestor
            notificationService.SendNotification(entityPO.Staff1.Person.OfficialEmail, notificationMsg, NotificationHelper.posubject);
            return LoadRejectPO(rejectedPO.Id);
        }

        #endregion

        #region .Request For Payment.

        public ActionResult ReviewRFP(Guid id, List<BudgetCheckResult> brcList = null)
        {
            PaymentRequest rfp = request4PaymentService.GetRFPById(id);
            List<PaymentRequestBudgetLine> rfpBLs = request4PaymentService.GetRFPDetails(rfp.Id);
            if (rfp.PurchaseOrderId != Guid.Empty)
                ViewBag.RefDocType = Resources.Global_String_PONo;
            else if (rfp.RequestForAdvanceId != Guid.Empty)
                ViewBag.RefDocType = Resources.Global_String_RFANo;
            else if (rfp.TravelAuthorisationId != Guid.Empty)
                ViewBag.RefDocType = Resources.Global_String_TAFNo;
            List<Models.ReviewRFPDetails> rfpDetailsList = new List<Models.ReviewRFPDetails>();
            List<ProjectDonor> pdList = budgetService.GetProjectDonors(countryProg);
            List<BudgetLineView> blList;

            foreach (PaymentRequestBudgetLine item in rfpBLs)
            {
                blList = orderRequestService.GetProjectBugdetLines(item.ProjectBudget.BudgetCategory.ProjectDonor.Id);
                var pdatils = new Models.ReviewRFPDetails()
                {
                    BudgetLineId = item.BudgetLineId,
                    ProjectDonorId = item.ProjectBudget.BudgetCategory.ProjectDonor.Id,
                    Amount = (decimal)item.Amount,
                    ProjectDonors = new SelectList(pdList, "Id", "ProjectNumber", item.ProjectBudget.BudgetCategory.ProjectDonorId),
                    BudgetLines = new SelectList(blList, "Id", "Description", item.BudgetLineId),
                    RFPDetailId = item.Id
                };
                rfpDetailsList.Add(pdatils);
            }

            var model = new Models.ReviewRFP()
            {
                EntityPaymentRqst = rfp,
                paymentDetails = rfpDetailsList,
                MBCurrencyId = mbCurrency.Id,
                Currencies = new SelectList(orderRequestService.GetCurrencies(countryProg.Id), "Id", "ShortName", mbCurrency.Id),
                BudgetCheckResults = brcList
            };
            return View("ReviewRFP", model);
        }

        public ActionResult LoadRFPForAuth(Guid id, List<BudgetCheckResult> brcList = null)
        {
            PaymentRequest rfp = request4PaymentService.GetRFPById(id);
            List<PaymentRequestBudgetLine> rfpBLs = request4PaymentService.GetRFPDetails(rfp.Id);
            if (rfp.PurchaseOrderId != Guid.Empty)
                ViewBag.RefDocType = Resources.Global_String_PONo;
            else if (rfp.RequestForAdvanceId != Guid.Empty)
                ViewBag.RefDocType = Resources.Global_String_RFANo;
            else if (rfp.TravelAuthorisationId != Guid.Empty)
                ViewBag.RefDocType = Resources.Global_String_TAFNo;
            List<Models.ReviewRFPDetails> rfpDetailsList = new List<Models.ReviewRFPDetails>();
            List<ProjectDonor> pdList = budgetService.GetProjectDonors(countryProg);
            List<BudgetLineView> blList;

            foreach (PaymentRequestBudgetLine item in rfpBLs)
            {
                blList = orderRequestService.GetProjectBugdetLines(item.ProjectBudget.BudgetCategory.ProjectDonor.Id);
                var pdatils = new Models.ReviewRFPDetails()
                {
                    BudgetLineId = item.BudgetLineId,
                    ProjectDonorId = item.ProjectBudget.BudgetCategory.ProjectDonor.Id,
                    Amount = (decimal)item.Amount,
                    ProjectDonors = new SelectList(pdList, "Id", "ProjectNumber", item.ProjectBudget.BudgetCategory.ProjectDonorId),
                    BudgetLines = new SelectList(blList, "Id", "Description", item.BudgetLineId),
                    RFPDetailId = item.Id
                };
                rfpDetailsList.Add(pdatils);
            }

            var model = new Models.ReviewRFP()
            {
                EntityPaymentRqst = rfp,
                paymentDetails = rfpDetailsList,
                MBCurrencyId = (Guid)rfp.MBCurrencyId,
                Currencies = new SelectList(orderRequestService.GetCurrencies(countryProg.Id), "Id", "ShortName", rfp.MBCurrencyId),
                BudgetCheckResults = brcList
            };

            //Reviewer and Authorizer Details
            if (model.EntityPaymentRqst.ReviewedBy != null)
            {
                Staff reviewer = staffService.GetStaffById((Guid)model.EntityPaymentRqst.ReviewedBy);
                ViewBag.Reviewer = reviewer.Person.FirstName + " " + reviewer.Person.OtherNames;
                ViewBag.ReviewerTitle = reviewer.Designation.Name;
                ViewBag.ReviewedOn = model.EntityPaymentRqst.ReviewedOn;
            }
            return View("AuthorizeRFP", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ApproveRFP(Models.ReviewRFP rfpModel)
        {
            Model.PaymentRequest entityRFP = request4PaymentService.GetRFPById(rfpModel.EntityPaymentRqst.Id);
            Model.PaymentRequestBudgetLine entityRFPDetail;
            entityRFP.MBCurrencyId = rfpModel.MBCurrencyId;
            entityRFP.MBValue = rfpModel.MBValue;
            entityRFP.TotalAmount = 0;
            foreach (Models.ReviewRFPDetails rfpDetail in rfpModel.paymentDetails)
            {
                entityRFPDetail = request4PaymentService.GetRFPDetailById(rfpDetail.RFPDetailId);
                entityRFPDetail.BudgetLineId = rfpDetail.BudgetLineId;
                entityRFPDetail.Amount = rfpDetail.Amount;
                entityRFP.TotalAmount += entityRFPDetail.Amount;
                request4PaymentService.SaveRFPDetail(entityRFPDetail);
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = request4PaymentService.RunFundsAvailableCheck(rfpModel.EntityPaymentRqst.Id);
            if (bcrList.Count > 0)
                return ReviewRFP(rfpModel.EntityPaymentRqst.Id, bcrList);

            entityRFP.IsReviewed = true;
            entityRFP.ReviewedBy = currentStaff.Id;
            entityRFP.ReviewedOn = DateTime.Now;
            request4PaymentService.SaveRFP(entityRFP);
            //Notify Autorizer and PMs
            notificationService.SendToAppropriateApprover(NotificationHelper.rfpCode, NotificationHelper.authorizationCode, entityRFP.Id);
            //Send notification to sender that RFP has been approved
            notificationService.SendNotification(entityRFP.Staff1.Person.OfficialEmail, string.Format(NotificationHelper.rfpApprovedMsgBody, entityRFP.Staff1.Person.FirstName, entityRFP.RefNumber), NotificationHelper.rfpsubject);

            return GetRequests();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult AuthorizeRFP(Models.ReviewRFP rfpModel)
        {
            Model.PaymentRequest entityRFP = request4PaymentService.GetRFPById(rfpModel.EntityPaymentRqst.Id);
            Model.PaymentRequestBudgetLine entityRFPDetail;
            entityRFP.MBValue = rfpModel.MBValue;
            entityRFP.TotalAmount = 0;
            foreach (Models.ReviewRFPDetails rfpDetail in rfpModel.paymentDetails)
            {
                entityRFPDetail = request4PaymentService.GetRFPDetailById(rfpDetail.RFPDetailId);
                entityRFPDetail.BudgetLineId = rfpDetail.BudgetLineId;
                entityRFPDetail.Amount = rfpDetail.Amount;
                entityRFP.TotalAmount += entityRFPDetail.Amount;
                request4PaymentService.SaveRFPDetail(entityRFPDetail);
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = request4PaymentService.RunFundsAvailableCheck(rfpModel.EntityPaymentRqst.Id);
            if (bcrList.Count > 0)
                return LoadRFPForAuth(rfpModel.EntityPaymentRqst.Id, bcrList);

            entityRFP.IsAuthorized = true;
            entityRFP.AuthorizedBy = currentStaff.Id;
            entityRFP.AuthorizedOn = DateTime.Now;
            //TODO: EffectPosting to be done by Finance Dept
            if (request4PaymentService.CommitFunds(entityRFP))
            {
                request4PaymentService.SaveRFP(entityRFP);
                notificationService.SendToAppropriateApprover(NotificationHelper.rfpCode, NotificationHelper.postFundsCode, entityRFP.Id);
            }
            //Send notification to sender that RFP has been authorized
            notificationService.SendNotification(entityRFP.Staff1.Person.OfficialEmail, string.Format(NotificationHelper.rfpAuthorizedMsgBody, entityRFP.Staff1.Person.FirstName, entityRFP.RefNumber), NotificationHelper.rfpsubject);
            ViewBag.Message = string.Format(Resources.RequestReviewController_String_HasBeenAuthorized, entityRFP.RefNumber);
            ViewBag.PdfURL = "/Reports/Request4Payment/Pdf?RFPid=" + entityRFP.Id;
            return View("AuthComplete");
        }

        public ActionResult LoadRejectRFP(Guid Id)
        {
            Models.RejectRFP model = new Models.RejectRFP();
            PaymentRequest entityRFP = request4PaymentService.GetRFPById(Id);
            model.Id = entityRFP.Id;
            if (entityRFP.IsReviewed == true)
            {
                model.IsReview = false;
                model.RejectedReviewRemarks = Resources.Global_String_None;
            }
            else
            {
                model.IsReview = true;
                model.RejectedAuthRemarks = Resources.Global_String_None;
            }
            return View("RejectRFP", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult RejectRFP(Models.RejectRFP rejectedRFP)
        {
            string notificationMsg;
            PaymentRequest entityRFP = request4PaymentService.GetRFPById(rejectedRFP.Id);
            entityRFP.IsRejected = true;
            if (rejectedRFP.IsReview)
            {
                entityRFP.RejectedReviewRemarks = rejectedRFP.RejectedReviewRemarks;
                entityRFP.ReviewedBy = currentStaff.Id;
                entityRFP.ReviewedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.rfpRejectedMsgBody, entityRFP.Staff1.Person.FirstName, entityRFP.RefNumber, entityRFP.RejectedReviewRemarks);
            }
            else
            {
                entityRFP.RejectedAuthorizeRemarks = rejectedRFP.RejectedAuthRemarks;
                entityRFP.AuthorizedBy = currentStaff.Id;
                entityRFP.AuthorizedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.rfpRejectedMsgBody, entityRFP.Staff1.Person.FirstName, entityRFP.RefNumber, entityRFP.RejectedAuthorizeRemarks);
            }
            request4PaymentService.SaveRFP(entityRFP);
            //Notify Project Manager(s)
            notificationService.SendRejectedMsgToPMs(NotificationHelper.rfpCode, entityRFP.Id, notificationMsg);
            //Notify Requestor
            notificationService.SendNotification(entityRFP.Staff1.Person.OfficialEmail, notificationMsg, NotificationHelper.rfpsubject);
            return LoadRejectRFP(rejectedRFP.Id);
        }

        #endregion

        #region .Request For Advance.

        public ActionResult ReviewRFA(Guid id, List<BudgetCheckResult> bcrList)
        {
            AdvanceRequest rfa = rfaService.GetRFAById(id);
            List<AdvanceRequestBudgetLine> rfaBLs = rfaService.GetRFADetails(rfa.Id);
            List<Models.AdvanceRequestBLModel> rfaDetailsList = new List<Models.AdvanceRequestBLModel>();
            List<ProjectDonor> pdList = budgetService.GetProjectDonors(countryProg);
            List<BudgetLineView> blList;

            foreach (AdvanceRequestBudgetLine item in rfaBLs)
            {
                blList = orderRequestService.GetProjectBugdetLines(item.ProjectBudget.BudgetCategory.ProjectDonor.Id);
                var rfaDetails = Models.AdvanceRequestBLExtension.ToModel(item);
                rfaDetails.ProjectNos = new SelectList(pdList, "Id", "ProjectNumber", item.ProjectBudget.BudgetCategory.ProjectDonorId);
                rfaDetails.BudgetLines = new SelectList(blList, "Id", "Description", item.BudgetLineId);
                rfaDetailsList.Add(rfaDetails);
            }

            var model = Models.AdvanceRequestExtension.ToModel(rfa);
            model.Currencies = new SelectList(orderRequestService.GetCurrencies(countryProg.Id), "Id", "ShortName", mbCurrency.Id);
            model.MBCurrency = mbCurrency.Id;
            model.PaymentDetails = rfaDetailsList;
            model.BudgetCheckResults = bcrList;
            return View("ReviewRFA", model);
        }

        public ActionResult LoadRFAForAuth(Guid id, List<BudgetCheckResult> bcrList)
        {
            AdvanceRequest rfa = rfaService.GetRFAById(id);
            List<AdvanceRequestBudgetLine> rfaBLs = rfaService.GetRFADetails(rfa.Id);
            List<Models.AdvanceRequestBLModel> rfaDetailsList = new List<Models.AdvanceRequestBLModel>();
            List<ProjectDonor> pdList = budgetService.GetProjectDonors(countryProg);
            List<BudgetLineView> blList;

            foreach (AdvanceRequestBudgetLine item in rfaBLs)
            {
                blList = orderRequestService.GetProjectBugdetLines(item.ProjectBudget.BudgetCategory.ProjectDonor.Id);
                var rfaDetails = Models.AdvanceRequestBLExtension.ToModel(item);
                rfaDetails.ProjectNos = new SelectList(pdList, "Id", "ProjectNumber", item.ProjectBudget.BudgetCategory.ProjectDonorId);
                rfaDetails.BudgetLines = new SelectList(blList, "Id", "Description", item.BudgetLineId);
                rfaDetailsList.Add(rfaDetails);
            }

            var model = Models.AdvanceRequestExtension.ToModel(rfa);
            model.Currencies = new SelectList(orderRequestService.GetCurrencies(countryProg.Id), "Id", "ShortName", (Guid)rfa.MBCurrency);
            model.MBCurrency = (Guid)rfa.MBCurrency;
            model.PaymentDetails = rfaDetailsList;
            model.BudgetCheckResults = bcrList;
            return View("AuthorizeRFA", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ApproveRFA(Models.AdvanceRequestModel rfaModel)
        {
            AdvanceRequest entityRFA = rfaService.GetRFAById(rfaModel.Id);
            AdvanceRequestBudgetLine entityRFADetail;
            entityRFA.MBCurrency = rfaModel.MBCurrency;
            entityRFA.MBTotal = rfaModel.MBValue;
            entityRFA.AccountNo = rfaModel.AccountNo;
            entityRFA.VoucherNo = rfaModel.VoucherNo;
            entityRFA.TotalAdvance = 0;
            foreach (Models.AdvanceRequestBLModel rfaDetail in rfaModel.PaymentDetails)
            {
                entityRFADetail = rfaService.GetRFABLById(rfaDetail.Id);
                entityRFADetail.BudgetLineId = rfaDetail.BudgetLineID;
                entityRFADetail.Amount = rfaDetail.Amount;
                entityRFA.TotalAdvance += entityRFADetail.Amount;
                rfaService.SaveRFADetail(entityRFADetail);
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = rfaService.RunFundsAvailableCheck(rfaModel.Id);
            if (bcrList.Count > 0)
                return ReviewRFA(rfaModel.Id, bcrList);

            entityRFA.IsReviewed = true;
            entityRFA.ReviewedBy = currentStaff.Id;
            entityRFA.ReviewedOn = DateTime.Now;
            rfaService.SaveRFA(entityRFA);
            //Notify Authorizer and Project Manager(s)
            notificationService.SendToAppropriateApprover(NotificationHelper.rfaCode, NotificationHelper.authorizationCode, entityRFA.Id);
            //Send notification to sender that RFP has been approved
            notificationService.SendNotification(entityRFA.Staff2.Person.OfficialEmail, string.Format(NotificationHelper.rfaApprovedMsgBody, entityRFA.Staff2.Person.FirstName, entityRFA.RefNumber), NotificationHelper.rfasubject);
            return GetRequests();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult AuthorizeRFA(Models.AdvanceRequestModel rfaModel)
        {
            AdvanceRequest entityRFA = rfaService.GetRFAById(rfaModel.Id);
            AdvanceRequestBudgetLine entityRFADetail;
            entityRFA.MBTotal = rfaModel.MBValue;
            entityRFA.TotalAdvance = 0;
            foreach (Models.AdvanceRequestBLModel rfaDetail in rfaModel.PaymentDetails)
            {
                entityRFADetail = rfaService.GetRFABLById(rfaDetail.Id);
                entityRFADetail.BudgetLineId = rfaDetail.BudgetLineID;
                entityRFADetail.Amount = rfaDetail.Amount;
                entityRFA.TotalAdvance += entityRFADetail.Amount;
                rfaService.SaveRFADetail(entityRFADetail);
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = rfaService.RunFundsAvailableCheck(rfaModel.Id);
            if (bcrList.Count > 0)
                return LoadRFAForAuth(rfaModel.Id, bcrList);

            entityRFA.IsAuthorized = true;
            entityRFA.AuthorizedBy = currentStaff.Id;
            entityRFA.AuthorizedOn = DateTime.Now;
            rfaService.SaveRFA(entityRFA);
            //Commit funds
            rfaService.CommitFunds(entityRFA);
            //Notify Funds Poster and Project Managers
            notificationService.SendToAppropriateApprover(NotificationHelper.rfaCode, NotificationHelper.postFundsCode, entityRFA.Id);
            //Send notification to sender that RFP has been authorized
            notificationService.SendNotification(entityRFA.Staff2.Person.OfficialEmail, string.Format(NotificationHelper.rfpAuthorizedMsgBody, entityRFA.Staff2.Person.FirstName, entityRFA.RefNumber), NotificationHelper.rfasubject);
            ViewBag.Message = string.Format(Resources.RequestReviewController_String_HasBeenAuthorized, entityRFA.RefNumber);
            ViewBag.PdfURL = "/Reports/R4A/pdf?R4Aid=" + entityRFA.Id;
            return View("AuthComplete");
        }

        public ActionResult LoadRejectRFA(Guid Id)
        {
            Models.RejectRFA model = new Models.RejectRFA();
            AdvanceRequest entityRFA = rfaService.GetRFAById(Id);
            model.RefNumber = entityRFA.RefNumber;
            model.Id = entityRFA.Id;
            if (entityRFA.IsReviewed == true)
            {
                model.IsReview = false;
                model.RejectedReviewRemarks = Resources.Global_String_None;
            }
            else
            {
                model.IsReview = true;
                model.RejectedAuthRemarks = Resources.Global_String_None;
            }
            return View("RejectRFA", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult RejectRFA(Models.RejectRFA rejectedRFA)
        {
            string notificationMsg;
            AdvanceRequest entityRFA = rfaService.GetRFAById(rejectedRFA.Id);
            entityRFA.IsRejected = true;
            if (rejectedRFA.IsReview)
            {
                entityRFA.RejectedReviewRemarks = rejectedRFA.RejectedReviewRemarks;
                entityRFA.ReviewedBy = currentStaff.Id;
                entityRFA.ReviewedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.rfaRejectedMsgBody, entityRFA.Staff2.Person.FirstName, entityRFA.RefNumber, entityRFA.RejectedReviewRemarks);
            }
            else
            {
                entityRFA.RejectedAuthorizeRemarks = rejectedRFA.RejectedAuthRemarks;
                entityRFA.AuthorizedBy = currentStaff.Id;
                entityRFA.AuthorizedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.rfaRejectedMsgBody, entityRFA.Staff2.Person.FirstName, entityRFA.RefNumber, entityRFA.RejectedAuthorizeRemarks);
            }
            rfaService.SaveRFA(entityRFA);
            //Notify PMs
            notificationService.SendRejectedMsgToPMs(NotificationHelper.rfaCode, entityRFA.Id, notificationMsg);
            //Notify requestor
            notificationService.SendNotification(entityRFA.Staff2.Person.OfficialEmail, notificationMsg, NotificationHelper.rfasubject);
            return LoadRejectRFA(rejectedRFA.Id);
        }

        #endregion

        #region .Warehouse Release Order.

        public ActionResult LoadWRO(Guid id)
        {
            using (var db = new SCMSEntities())
            {
                WarehouseRelease wrnenttiy = db.WarehouseReleases.First(p => p.Id == id);
                List<Model.WarehouseReleaseItem> writms = wrnenttiy.WarehouseReleaseItems.ToList();
                foreach (WarehouseReleaseItem item in writms)
                {
                    Model.Inventory a = item.Inventory;
                    Model.Item i = a.Item;
                    Model.ItemCategory ic = i.ItemCategory;
                    Model.Asset ast = item.Asset;
                    Model.UnitOfMeasure u = a.Item.UnitOfMeasure;
                }
                //Dummies
                if (wrnenttiy.Staff != null)
                {
                    var person = wrnenttiy.Staff.Person;
                    var desg = wrnenttiy.Staff.Designation;
                    var office = wrnenttiy.Staff.CountrySubOffice;
                }
                if (wrnenttiy.Staff1 != null)
                {
                    var person = wrnenttiy.Staff1.Person;
                    var desg = wrnenttiy.Staff1.Designation;
                    var office = wrnenttiy.Staff1.CountrySubOffice;
                }
                if (wrnenttiy.Staff2 != null)
                {
                    var person = wrnenttiy.Staff2.Person;
                    var desg = wrnenttiy.Staff2.Designation;
                    var office = wrnenttiy.Staff2.CountrySubOffice;
                }
                var model = new Models.ViewWRNDetails()
                {
                    EntityWHouseRelease = wrnenttiy,
                    writems = writms,
                    Requestor = db.VStaffDetails.First(p => p.StaffID == wrnenttiy.PreparedBy),
                    Recipient = db.VStaffDetails.First(p => p.StaffID == wrnenttiy.ReceivedBy)
                };
                return View(model);
            }
        }
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ApproveWRO(Models.ViewWRNs wroModel)
        {
            WarehouseRelease entityWRO = wroService.GetWROById(wroModel.EntityWHouseRelease.Id);
            entityWRO.IsApproved = true;
            entityWRO.ApprovedBy = currentStaff.Id;
            entityWRO.ApprovedOn = DateTime.Now;
            wroService.SaveApproved(entityWRO);
            //Send notification to sender that RFP has been approved
            notificationService.SendNotification(entityWRO.Staff1.Person.OfficialEmail, string.Format(NotificationHelper.wrnApprovedMsgBody, entityWRO.Staff1.Person.FirstName, entityWRO.RefNumber), NotificationHelper.wrnsubject);
            //Response.Redirect("/Request4Payment/ViewR4PDetails/" + entityRFP.Id);
            ViewBag.Message = string.Format(Resources.RequestReviewController_String_HasBeenApproved, entityWRO.RefNumber);
            ViewBag.PdfURL = "/Reports/WareHouse/ReleaseForm?WRNid=" + entityWRO.Id;
            return View("AuthComplete");
        }

        public ActionResult LoadRejectWRO(Guid Id)
        {
            Models.RejectWRO model = new Models.RejectWRO();
            WarehouseRelease entityWRO = wroService.GetWROById(Id);
            model.Id = entityWRO.Id;
            model.RefNumber = entityWRO.RefNumber;
            return View("RejectWRO", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult RejectWRO(Models.RejectWRO rejectedWRO)
        {
            string notificationMsg;
            WarehouseRelease entityWRO = wroService.GetWROById(rejectedWRO.Id);
            entityWRO.IsApproved = false;
            entityWRO.IsRejected = true;
            entityWRO.RejectedWRFComments = rejectedWRO.RejectedReviewRemarks;
            entityWRO.RejectedOn = DateTime.Now;
            wroService.SaveApproved(entityWRO);
            wroService.RejectWRO(entityWRO.Id);
            //Notify preparer
            notificationMsg = string.Format(NotificationHelper.wroRejectedMsgBody, entityWRO.Staff1.Person.FirstName, entityWRO.RefNumber, entityWRO.RejectedWRFComments);
            notificationService.SendNotification(entityWRO.Staff1.Person.OfficialEmail, notificationMsg, NotificationHelper.wrnsubject);
            return LoadRejectWRO(rejectedWRO.Id);
        }

        #endregion

        #region .Expense Claim Form.

        public ActionResult ReviewECF(Guid id, List<BudgetCheckResult> bcrList = null)
        {
            ExpenseRequest ecf = expenseClaimService.GetExpenseClaimById(id);
            List<ExpenseItem> ecfItems = expenseClaimService.GetExpenseItems(ecf.Id);
            List<Models.ExpsClaimItems> ecfModelItems = new List<Models.ExpsClaimItems>();
            List<ProjectDonor> pdList = budgetService.GetProjectDonors(countryProg);
            List<BudgetLineView> blList;
            List<AccountCode> accountCodes = expenseClaimService.GetAccountCodes(countryProg.Id);
            //Get conversion rate of ECF Expense currency to MB Currency
            Models.ViewExpsClaims model = new Models.ViewExpsClaims
            {
                EntityExpseRqst = ecf,
                Currencies = new SelectList(orderRequestService.GetCurrencies(countryProg.Id), "Id", "ShortName"),
                ExpenseClaimItems = ecfModelItems,
                MBCurrencyId = mbCurrency.Id,
                ConversionCurrencyId = mbCurrency.Id,
                ExpsCurrency = ecf.Currency,
                ConversionRate = ecf.ExchangeRate,
                BudgetCheckResults = bcrList
            };

            foreach (ExpenseItem ecfItem in ecfItems)
            {
                blList = orderRequestService.GetProjectBugdetLines(ecfItem.ProjectBudget.BudgetCategory.ProjectDonor.Id);
                ecfModelItems.Add(new Models.ExpsClaimItems
                {
                    EntityExpseItem = ecfItem,
                    ProjectDonors = new SelectList(pdList, "Id", "ProjectNumber", ecfItem.ProjectBudget.BudgetCategory.ProjectDonor.Id),
                    BudgetLines = new SelectList(blList, "Id", "Description", ecfItem.BudgetLineId),
                    AccountCodes = new SelectList(accountCodes, "Id", "Code")
                });
            }

            return View("ReviewECF", model);
        }

        public ActionResult LoadECFForAuth(Guid id, List<BudgetCheckResult> bcrList = null)
        {
            ExpenseRequest ecf = expenseClaimService.GetExpenseClaimById(id);
            List<ExpenseItem> ecfItems = expenseClaimService.GetExpenseItems(ecf.Id);
            List<Models.ExpsClaimItems> ecfModelItems = new List<Models.ExpsClaimItems>();
            List<ProjectDonor> pdList = budgetService.GetProjectDonors(countryProg);
            List<BudgetLineView> blList;
            List<AccountCode> accountCodes = expenseClaimService.GetAccountCodes(countryProg.Id);
            Models.ViewExpsClaims model = new Models.ViewExpsClaims
            {
                EntityExpseRqst = ecf,
                Currencies = new SelectList(orderRequestService.GetCurrencies(countryProg.Id), "Id", "ShortName", mbCurrency.Id),
                ExpenseClaimItems = ecfModelItems,
                MBCurrencyId = mbCurrency.Id,
                ConversionCurrencyId = mbCurrency.Id,
                ExpsCurrency = ecf.Currency,
                ConversionRate = ecf.ExchangeRate,
                MBValue = (decimal)ecf.MBTotal,
                BudgetCheckResults = bcrList
            };

            foreach (ExpenseItem ecfItem in ecfItems)
            {
                blList = orderRequestService.GetProjectBugdetLines(ecfItem.ProjectBudget.BudgetCategory.ProjectDonor.Id);
                ecfModelItems.Add(new Models.ExpsClaimItems
                {
                    EntityExpseItem = ecfItem,
                    ProjectDonors = new SelectList(pdList, "Id", "ProjectNumber", ecfItem.ProjectBudget.BudgetCategory.ProjectDonor.Id),
                    BudgetLines = new SelectList(blList, "Id", "Description", ecfItem.BudgetLineId),
                    AccountCodes = new SelectList(accountCodes, "Id", "Code")
                });
            }
            return View("AuthorizeECF", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ApproveECF(Models.ViewExpsClaims ecfModel)
        {
            ExpenseRequest entityECF = expenseClaimService.GetExpenseClaimById(ecfModel.EntityExpseRqst.Id);
            ExpenseItem entityECFItem;
            entityECF.CurrencyConvertedTo = ecfModel.ConversionCurrencyId;
            entityECF.ExchangeRate = ecfModel.ConversionRate;
            entityECF.MBCurrency = ecfModel.MBCurrencyId;
            entityECF.MBTotal = ecfModel.MBValue;
            entityECF.TotalValue = 0;
            foreach (Models.ExpsClaimItems ecfItem in ecfModel.ExpenseClaimItems)
            {
                entityECFItem = expenseClaimService.GetExpenseItemById(ecfItem.EntityExpseItem.Id);
                entityECFItem.BudgetLineId = ecfItem.BudgetLineId;
                entityECFItem.AccountCodeId = ecfItem.AccountCode;
                entityECFItem.ItemAmount = ecfItem.Amount;
                entityECFItem.ConvertedAmount = ecfItem.EntityExpseItem.ConvertedAmount;
                entityECF.TotalValue += entityECFItem.ItemAmount;
                expenseClaimService.SaveApprovedECFItem(entityECFItem);
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = expenseClaimService.RunFundsAvailableCheck(ecfModel.EntityExpseRqst.Id);
            if (bcrList.Count > 0)
                return ReviewECF(ecfModel.EntityExpseRqst.Id, bcrList);

            entityECF.IsReviewed = true;
            entityECF.ReviewedBy = currentStaff.Id;
            entityECF.ReviewedOn = DateTime.Now;
            expenseClaimService.SaveApprovedECF(entityECF);
            //Notify authorizer
            notificationService.SendToAppropriateApprover(NotificationHelper.ecfCode, NotificationHelper.authorizationCode, entityECF.Id);
            //Send notification to sender that ECF has been approved
            notificationService.SendNotification(entityECF.Staff2.Person.OfficialEmail, string.Format(NotificationHelper.ecfApprovedMsgBody, entityECF.Staff2.Person.FirstName, entityECF.RefNumber), NotificationHelper.ecfsubject);
            return GetRequests();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult AuthorizeECF(Models.ViewExpsClaims ecfModel)
        {
            ExpenseRequest entityECF = expenseClaimService.GetExpenseClaimById(ecfModel.EntityExpseRqst.Id);
            ExpenseItem entityECFItem;
            entityECF.MBTotal = ecfModel.MBValue;
            entityECF.TotalValue = 0;
            foreach (Models.ExpsClaimItems ecfItem in ecfModel.ExpenseClaimItems)
            {
                entityECFItem = expenseClaimService.GetExpenseItemById(ecfItem.EntityExpseItem.Id);
                entityECFItem.BudgetLineId = ecfItem.BudgetLineId;
                entityECFItem.AccountCodeId = ecfItem.AccountCode;
                entityECFItem.ItemAmount = ecfItem.Amount;
                entityECFItem.ConvertedAmount = ecfItem.EntityExpseItem.ConvertedAmount;
                entityECF.TotalValue += entityECFItem.ItemAmount;
                expenseClaimService.SaveApprovedECFItem(entityECFItem);
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = expenseClaimService.RunFundsAvailableCheck(ecfModel.EntityExpseRqst.Id);
            if (bcrList.Count > 0)
                return LoadECFForAuth(ecfModel.EntityExpseRqst.Id, bcrList);

            entityECF.IsAuthorized = true;
            entityECF.AuthorizedBy = currentStaff.Id;
            entityECF.AuthorizedOn = DateTime.Now;
            expenseClaimService.SaveApprovedECF(entityECF);
            //Commit Funds
            expenseClaimService.CommitFunds(entityECF);
            //Notify Funds Poster and PMs
            notificationService.SendToAppropriateApprover(NotificationHelper.ecfCode, NotificationHelper.postFundsCode, entityECF.Id);
            //Send notification to sender that ECF has been authorized
            notificationService.SendNotification(entityECF.Staff2.Person.OfficialEmail, string.Format(NotificationHelper.ecfAuthorizedMsgBody, entityECF.Staff2.Person.FirstName, entityECF.RefNumber), NotificationHelper.ecfsubject);
            ViewBag.Message = string.Format(Resources.RequestReviewController_String_HasBeenAuthorized, entityECF.RefNumber);
            ViewBag.PdfURL = "/Reports/EClaim/Pdf?ECid=" + entityECF.Id;
            return View("AuthComplete");
        }

        public ActionResult LoadRejectECF(Guid Id)
        {
            Models.RejectECF model = new Models.RejectECF();
            ExpenseRequest entityECF = expenseClaimService.GetExpenseClaimById(Id);
            model.RefNumber = entityECF.RefNumber;
            model.Id = entityECF.Id;
            if (entityECF.IsReviewed == true)
            {
                model.IsReview = false;
                model.RejectedReviewRemarks = Resources.Global_String_None;
            }
            else
            {
                model.IsReview = true;
                model.RejectedAuthRemarks = Resources.Global_String_None;
            }
            return View("RejectECF", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult RejectECF(Models.RejectECF rejectedECF)
        {
            string notificationMsg;
            ExpenseRequest entityECF = expenseClaimService.GetExpenseClaimById(rejectedECF.Id);
            entityECF.IsRejected = true;
            if (rejectedECF.IsReview)
            {
                entityECF.RejectReviewRemarks = rejectedECF.RejectedReviewRemarks;
                entityECF.ReviewedBy = currentStaff.Id;
                entityECF.ReviewedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.ecfRejectedMsgBody, entityECF.Staff2.Person.FirstName, entityECF.RefNumber, entityECF.RejectReviewRemarks);
            }
            else
            {
                entityECF.RejectAuthorizedRemarks = rejectedECF.RejectedAuthRemarks;
                entityECF.AuthorizedBy = currentStaff.Id;
                entityECF.AuthorizedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.ecfRejectedMsgBody, entityECF.Staff2.Person.FirstName, entityECF.RefNumber, entityECF.RejectAuthorizedRemarks);
            }
            expenseClaimService.SaveApprovedECF(entityECF);
            //Notify PMs
            notificationService.SendRejectedMsgToPMs(NotificationHelper.ecfCode, entityECF.Id, notificationMsg);
            //Notify requestor
            notificationService.SendNotification(entityECF.Staff2.Person.OfficialEmail, notificationMsg, NotificationHelper.ecfsubject);
            return LoadRejectECF(rejectedECF.Id);
        }

        #endregion

        #region .Salary Payment.

        public ActionResult ReviewSPM(Guid id, List<BudgetCheckResult> bcrList = null)
        {
            SalaryRequest spm = salaryPaymentService.GetSalaryRequestById(id);
            List<SalaryBudgetline> spmItems = salaryPaymentService.GetSPBLines(spm.Id);
            List<Models.SalaryPaymentItems> spmModelItems = new List<Models.SalaryPaymentItems>();
            List<ProjectDonor> pdList = budgetService.GetProjectDonors(countryProg);
            List<BudgetLineView> blList;

            Models.SalaryPayment model = new Models.SalaryPayment
            {
                EntitySalaryP = spm,
                Currencies = new SelectList(orderRequestService.GetCurrencies(countryProg.Id), "Id", "ShortName", mbCurrency.Id),
                SalaryPaymentItems = spmModelItems,
                MBCurrencyId = mbCurrency.Id,
                BudgetCheckResults = bcrList
            };

            foreach (SalaryBudgetline spmItem in spmItems)
            {
                blList = orderRequestService.GetProjectBugdetLines(spmItem.ProjectBudget.BudgetCategory.ProjectDonor.Id);
                spmModelItems.Add(new Models.SalaryPaymentItems
                {
                    EntitySalaryPBL = spmItem,
                    ProjectNos = new SelectList(pdList, "Id", "ProjectNumber", spmItem.ProjectBudget.BudgetCategory.ProjectDonor.Id),
                    BudgetLines = new SelectList(blList, "Id", "Description", spmItem.BudgetLineId)
                });
            }

            return View("ReviewSPM", model);
        }

        public ActionResult LoadSPMForAuth(Guid id, List<BudgetCheckResult> bcrList = null)
        {
            SalaryRequest spm = salaryPaymentService.GetSalaryRequestById(id);
            List<SalaryBudgetline> spmItems = salaryPaymentService.GetSPBLines(spm.Id);
            List<Models.SalaryPaymentItems> spmModelItems = new List<Models.SalaryPaymentItems>();
            List<ProjectDonor> pdList = budgetService.GetProjectDonors(countryProg);
            List<BudgetLineView> blList;

            Models.SalaryPayment model = new Models.SalaryPayment
            {
                EntitySalaryP = spm,
                Currencies = new SelectList(orderRequestService.GetCurrencies(countryProg.Id), "Id", "ShortName", mbCurrency.Id),
                SalaryPaymentItems = spmModelItems,
                MBCurrencyId = (Guid)spm.MBCurrency,
                MBValue = (decimal)spm.MBTotal,
                BudgetCheckResults = bcrList
            };

            foreach (SalaryBudgetline spmItem in spmItems)
            {
                blList = orderRequestService.GetProjectBugdetLines(spmItem.ProjectBudget.BudgetCategory.ProjectDonor.Id);
                spmModelItems.Add(new Models.SalaryPaymentItems
                {
                    EntitySalaryPBL = spmItem,
                    ProjectNos = new SelectList(pdList, "Id", "ProjectNumber", spmItem.ProjectBudget.BudgetCategory.ProjectDonor.Id),
                    BudgetLines = new SelectList(blList, "Id", "Description", spmItem.BudgetLineId)
                });
            }
            return View("AuthorizeSPM", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ApproveSPM(Models.SalaryPayment spmModel)
        {
            SalaryRequest entitySPM = salaryPaymentService.GetSalaryRequestById(spmModel.EntitySalaryP.Id);
            SalaryBudgetline entitySPMItem;
            entitySPM.MBCurrency = spmModel.MBCurrencyId;
            entitySPM.MBTotal = spmModel.MBValue;
            entitySPM.TotalPayroll = 0;
            foreach (Models.SalaryPaymentItems spmItem in spmModel.SalaryPaymentItems)
            {
                entitySPMItem = salaryPaymentService.GetSalaryBudgetLineById(spmItem.EntitySalaryPBL.Id);
                entitySPMItem.BudgetLineId = spmItem.BudgetLineId;
                entitySPMItem.Amount = spmItem.EntitySalaryPBL.Amount;
                entitySPM.TotalPayroll += entitySPMItem.Amount;
                salaryPaymentService.SaveSalaryBudgetLine(entitySPMItem);
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = salaryPaymentService.RunFundsAvailableCheck(spmModel.EntitySalaryP.Id);
            if (bcrList.Count > 0)
                return ReviewSPM(spmModel.EntitySalaryP.Id, bcrList);

            entitySPM.IsReviewed = true;
            entitySPM.ReviewedBy = currentStaff.Id;
            entitySPM.ReviewedOn = DateTime.Now;
            salaryPaymentService.SaveSalaryRequest(entitySPM);
            //Notify Authorizer and PMs
            notificationService.SendToAppropriateApprover(NotificationHelper.spmCode, NotificationHelper.authorizationCode, entitySPM.Id);
            //Send notification to sender that SPM has been approved
            notificationService.SendNotification(entitySPM.Staff2.Person.OfficialEmail, string.Format(NotificationHelper.spmApprovedMsgBody, entitySPM.Staff2.Person.FirstName, entitySPM.RefNumber), NotificationHelper.spmsubject);
            return GetRequests();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult AuthorizeSPM(Models.SalaryPayment spmModel)
        {
            SalaryRequest entitySPM = salaryPaymentService.GetSalaryRequestById(spmModel.EntitySalaryP.Id);
            SalaryBudgetline entitySPMItem;
            entitySPM.MBTotal = spmModel.MBValue;
            entitySPM.TotalPayroll = 0;
            foreach (Models.SalaryPaymentItems spmItem in spmModel.SalaryPaymentItems)
            {
                entitySPMItem = salaryPaymentService.GetSalaryBudgetLineById(spmItem.EntitySalaryPBL.Id);
                entitySPMItem.BudgetLineId = spmItem.BudgetLineId;
                entitySPMItem.Amount = spmItem.EntitySalaryPBL.Amount;
                entitySPM.TotalPayroll += entitySPMItem.Amount;
                salaryPaymentService.SaveSalaryBudgetLine(entitySPMItem);
            }

            //Run another check on funds availability
            List<BudgetCheckResult> bcrList = salaryPaymentService.RunFundsAvailableCheck(spmModel.EntitySalaryP.Id);
            if (bcrList.Count > 0)
                return LoadSPMForAuth(spmModel.EntitySalaryP.Id, bcrList);

            entitySPM.IsAuthorized = true;
            entitySPM.AuthorizedBy = currentStaff.Id;
            entitySPM.AuthorizedOn = DateTime.Now;
            salaryPaymentService.SaveSalaryRequest(entitySPM);
            //Commit Funds
            salaryPaymentService.CommitFunds(entitySPM);
            //Notify Funds Poster and PMs
            notificationService.SendToAppropriateApprover(NotificationHelper.spmCode, NotificationHelper.postFundsCode, entitySPM.Id);
            //Send notification to sender that SPM has been authorized
            notificationService.SendNotification(entitySPM.Staff2.Person.OfficialEmail, string.Format(NotificationHelper.spmAuthorizedMsgBody, entitySPM.Staff2.Person.FirstName, entitySPM.RefNumber), NotificationHelper.spmsubject);

            ViewBag.Message = string.Format(Resources.RequestReviewController_String_HasBeenAuthorized, entitySPM.RefNumber);
            ViewBag.PdfURL = "/Reports/SP/pdf?SPid=" + entitySPM.Id;
            return View("AuthComplete");
        }

        public ActionResult LoadRejectSPM(Guid Id)
        {
            Models.RejectSPM model = new Models.RejectSPM();
            SalaryRequest entitySPM = salaryPaymentService.GetSalaryRequestById(Id);
            model.RefNumber = entitySPM.RefNumber;
            model.Id = entitySPM.Id;
            if (entitySPM.IsReviewed == true)
            {
                model.IsReview = false;
                model.RejectedReviewRemarks = Resources.Global_String_None;
            }
            else
            {
                model.IsReview = true;
                model.RejectedAuthRemarks = Resources.Global_String_None;
            }
            return View("RejectSPM", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult RejectSPM(Models.RejectSPM rejectedSPM)
        {
            string notificationMsg;
            SalaryRequest entitySPM = salaryPaymentService.GetSalaryRequestById(rejectedSPM.Id);
            entitySPM.IsRejected = true;
            if (rejectedSPM.IsReview)
            {
                entitySPM.RejectReviewRemarks = rejectedSPM.RejectedReviewRemarks;
                entitySPM.ReviewedBy = currentStaff.Id;
                entitySPM.ReviewedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.spmRejectedMsgBody, entitySPM.Staff2.Person.FirstName, entitySPM.RefNumber, entitySPM.RejectReviewRemarks);
            }
            else
            {
                entitySPM.RejectAuthorizedRemarks = rejectedSPM.RejectedAuthRemarks;
                entitySPM.AuthorizedBy = currentStaff.Id;
                entitySPM.AuthorizedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.spmRejectedMsgBody, entitySPM.Staff2.Person.FirstName, entitySPM.RefNumber, entitySPM.RejectAuthorizedRemarks);
            }
            salaryPaymentService.SaveSalaryRequest(entitySPM);
            //Notify Authorizer and PMs
            notificationService.SendRejectedMsgToPMs(NotificationHelper.spmCode, entitySPM.Id, notificationMsg);
            //Notify requestor
            notificationService.SendNotification(entitySPM.Staff2.Person.OfficialEmail, notificationMsg, NotificationHelper.spmsubject);
            return LoadRejectSPM(rejectedSPM.Id);
        }

        #endregion
        
        #region .Travel Authorization.

        public ActionResult ReviewTAF(Guid id)
        {
            Models.ViewTAForms model = TAFExtention.PrepareTAF(id);
            model.Currencies = new SelectList(orderRequestService.GetCurrencies(countryProg.Id), "Id", "ShortName", mbCurrency.Id);
            model.MBCurrencyId = mbCurrency.Id;
            model.TAuthFormEntity.TotalAmount = Math.Round(model.TAuthFormEntity.TotalAmount.Value, 2);
            return View(model);
        }

        public ActionResult LoadTAFForAuth(Guid id)
        {
            Models.ViewTAForms model = TAFExtention.PrepareTAF(id);
            List<Model.TravelDate> travelDates = tafService.GetTAFDates(id);
            List<Model.TravelExpense> travelExpenses = tafService.GetTAFExpenses(id);
            List<Models.TravelDate> viewTravelDates = new List<Models.TravelDate>();
            List<Models.TravelExpense> viewTravelExpenses = new List<Models.TravelExpense>();
            foreach (var travelDate in travelDates)
            {
                viewTravelDates.Add(new Models.TravelDate
                {
                    EntityTDate = travelDate,
                    BudgetLines = new SelectList(orderRequestService.GetProjectBugdetLines(travelDate.ProjectBudget.BudgetCategory.ProjectDonor.Id), "Id", "Description", travelDate.BudgetLineId),
                    ProjectNos = new SelectList(orderRequestService.GetProjectNos(countryProg.Id), "Id", "ProjectNumber", travelDate.ProjectBudget.BudgetCategory.ProjectDonor.Id),
                    ProjectId = travelDate.ProjectBudget.BudgetCategory.ProjectDonor.Id
                });
                travelDate.AdvanceRequired = Math.Round(travelDate.AdvanceRequired.Value, 2);
                travelDate.DailyPDRate = Math.Round(travelDate.DailyPDRate.Value, 2);
                travelDate.TotalAllowance = Math.Round(travelDate.TotalAllowance.Value, 2);
            }

            foreach (var travelExpense in travelExpenses)
            {
                viewTravelExpenses.Add(new Models.TravelExpense
                {
                    EntityTExpense = travelExpense,
                    BudgetLines = new SelectList(orderRequestService.GetProjectBugdetLines(travelExpense.ProjectBudget.BudgetCategory.ProjectDonor.Id), "Id", "Description", travelExpense.BudgetLineId),
                    ProjectNos = new SelectList(orderRequestService.GetProjectNos(countryProg.Id), "Id", "ProjectNumber", travelExpense.ProjectBudget.BudgetCategory.ProjectDonor.Id),
                    ProjectId = travelExpense.ProjectBudget.BudgetCategory.ProjectDonor.Id
                });
                travelExpense.AdvanceRequired = Math.Round(travelExpense.AdvanceRequired.Value, 2);
                travelExpense.TotalCost = Math.Round(travelExpense.TotalCost.Value, 2);
            }

            model.ViewTravelDates = viewTravelDates;
            model.ViewTravelExpenses = viewTravelExpenses;

            model.Currencies = new SelectList(orderRequestService.GetCurrencies(countryProg.Id), "Id", "ShortName", mbCurrency.Id);
            model.MBCurrencyId = mbCurrency.Id;
            model.TAuthFormEntity.TotalAmount = Math.Round(model.TAuthFormEntity.TotalAmount.Value, 2);
            model.MBValue = model.TAuthFormEntity.MBValue.HasValue ? Math.Round(model.TAuthFormEntity.MBValue.Value, 2) : 0;
            return View("AuthorizeTAF", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ApproveTAF(Models.ViewTAForms tafModel)
        {
            TravelAuthorization entityTAF = tafService.GetTAFById(tafModel.TAuthFormEntity.Id);            
            entityTAF.MBCurrencyId = tafModel.MBCurrencyId;
            entityTAF.MBValue = tafModel.MBValue;            
            entityTAF.IsReviewed = true;
            entityTAF.ApprovedBy = currentStaff.Id;
            entityTAF.ReviewedOn = DateTime.Now;
            tafService.SaveApprovedTAF(entityTAF);
            //Notify Authorizer and PMs
            notificationService.SendToAppropriateApprover(NotificationHelper.tafCode, NotificationHelper.authorizationCode, entityTAF.Id);
            //Send notification to sender that TAF has been approved
            notificationService.SendNotification(entityTAF.Staff3.Person.OfficialEmail, string.Format(NotificationHelper.tafApprovedMsgBody, entityTAF.Staff3.Person.FirstName, entityTAF.RefNumber), NotificationHelper.tafsubject);
            return GetRequests();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult AuthorizeTAF(Models.ViewTAForms tafModel)
        {
            TravelAuthorization entityTAF = tafService.GetTAFById(tafModel.TAuthFormEntity.Id);
            
            Model.TravelDate entityTravelDate;
            Model.TravelExpense entityTravelExpense;

            entityTAF.MBValue = tafModel.MBValue;
            entityTAF.TotalAmount = 0;
            //Update TAF Dates
            foreach (Models.TravelDate tafDate in tafModel.ViewTravelDates)
            {
                entityTravelDate = tafService.GetTAFDateById(tafDate.EntityTDate.Id);                
                entityTravelDate.BudgetLineId = tafDate.EntityTDate.BudgetLineId;
                entityTravelDate.TotalAllowance = tafDate.EntityTDate.TotalAllowance;
                entityTAF.TotalAmount += entityTravelDate.TotalAllowance;
                tafService.SaveApprovedTAFDate(entityTravelDate);
            }

            //Update TAF Expenses
            foreach (Models.TravelExpense tafExpenses in tafModel.ViewTravelExpenses)
            {
                entityTravelExpense = tafService.GetTAFExpenseById(tafExpenses.EntityTExpense.Id);
                entityTravelExpense.BudgetLineId = tafExpenses.EntityTExpense.BudgetLineId;
                entityTravelExpense.TotalCost = tafExpenses.EntityTExpense.TotalCost;
                entityTAF.TotalAmount += entityTravelExpense.TotalCost;
                tafService.SaveApprovedTAFExpense(entityTravelExpense);
            }

            entityTAF.IsAuthorized = true;
            entityTAF.AuthorizedBy = currentStaff.Id;
            entityTAF.AuthorizedOn = DateTime.Now;
            tafService.SaveApprovedTAF(entityTAF);
            //Commit Funds
            tafService.CommitFunds(entityTAF);
            //Notify Funds Poster and PMs
            notificationService.SendToAppropriateApprover(NotificationHelper.tafCode, NotificationHelper.postFundsCode, entityTAF.Id);
            //Send notification to sender that TAF has been authorized
            notificationService.SendNotification(entityTAF.Staff3.Person.OfficialEmail, string.Format(NotificationHelper.spmAuthorizedMsgBody, entityTAF.Staff3.Person.FirstName, entityTAF.RefNumber), NotificationHelper.tafsubject);

            ViewBag.Message = string.Format(Resources.RequestReviewController_String_HasBeenAuthorized, entityTAF.RefNumber);
            ViewBag.PdfURL = "/Reports/TAF/Index?TAFid=" + entityTAF.Id;
            return View("AuthComplete");
        }

        public ActionResult LoadRejectTAF(Guid Id)
        {
            Models.RejectTAF model = new Models.RejectTAF();
            TravelAuthorization entityTAF = tafService.GetTAFById(Id);
            model.RefNumber = entityTAF.RefNumber;
            model.Id = entityTAF.Id;
            if (entityTAF.IsReviewed == true)
            {
                model.IsReview = false;
                model.RejectedReviewRemarks = Resources.Global_String_None;
            }
            else
            {
                model.IsReview = true;
                model.RejectedAuthRemarks = Resources.Global_String_None;
            }
            return View("RejectTAF", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult RejectTAF(Models.RejectTAF rejectedTAF)
        {
            string notificationMsg;
            TravelAuthorization entityTAF = tafService.GetTAFById(rejectedTAF.Id);
            entityTAF.IsRejected = true;
            if (rejectedTAF.IsReview)
            {
                entityTAF.RejectReviewRemarks = rejectedTAF.RejectedReviewRemarks;
                entityTAF.ApprovedBy = currentStaff.Id;
                entityTAF.ReviewedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.tafRejectedMsgBody, entityTAF.Staff3.Person.FirstName, entityTAF.RefNumber, entityTAF.RejectReviewRemarks);
            }
            else
            {
                entityTAF.RejectAuthorizedRemarks = rejectedTAF.RejectedAuthRemarks;
                entityTAF.AuthorizedBy = currentStaff.Id;
                entityTAF.AuthorizedOn = DateTime.Now;
                notificationMsg = string.Format(NotificationHelper.tafRejectedMsgBody, entityTAF.Staff3.Person.FirstName, entityTAF.RefNumber, entityTAF.RejectAuthorizedRemarks);
            }
            tafService.SaveApprovedTAF(entityTAF);
            
            //Notify Authorizer and PMs
            notificationService.SendRejectedMsgToPMs(NotificationHelper.tafCode, entityTAF.Id, notificationMsg);
            //Notify requestor
            notificationService.SendNotification(entityTAF.Staff3.Person.OfficialEmail, notificationMsg, NotificationHelper.tafsubject);
            return LoadRejectTAF(rejectedTAF.Id);
        }

        #endregion

        #region .Procurement Plan.

        public ActionResult ApprovePP(Guid id)
        {
            PPModel model = PreparePPModel(id);
            return View("ApprovePP", model);
        }

        private PPModel PreparePPModel(Guid id)
        {
            ProcurementPlan pp = ppService.GetProcurementPlanById(id);
            PPModel model = new PPModel { EntityPP = pp };
            model.PPItems = new List<PPItemModel>();
            List<Model.ProcurementPlanItem> ppItems = ppService.GetProcurementPlanItems(pp.Id);
            List<BudgetLineView> budgetLines = orderRequestService.GetProjectBugdetLines(pp.ProjectDonorId);
            foreach (ProcurementPlanItem ppItem in ppItems)
                if (!ppItem.IsApproved)
                {
                    ppItem.UnitCost = Math.Round(ppItem.UnitCost, 2);
                    ppItem.TotalCost = Math.Round(ppItem.TotalCost, 2);
                    model.PPItems.Add(new PPItemModel { EntityPPItem = ppItem, BudgetLines = new SelectList(budgetLines, "Id", "Description", ppItem.BudgetLineId) });
                }
            return model;
        }

        /// <summary>
        /// Approve PP
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult ApprovePP(PPModel model)
        {
            ProcurementPlanItem item;
            foreach (var ppItem in model.PPItems)
            {
                if (!ppItem.EntityPPItem.IsApproved)
                    continue;
                item = ppService.GetProcurementPlanItemById(ppItem.EntityPPItem.Id);
                item.Quantity = ppItem.EntityPPItem.Quantity;
                item.UnitCost = ppItem.EntityPPItem.UnitCost;
                item.TotalCost = ppItem.EntityPPItem.Quantity * ppItem.EntityPPItem.UnitCost;
                item.BudgetLineId = ppItem.EntityPPItem.BudgetLineId;
                item.IsApproved = true;
                ppService.SaveProcurementPlanItem(item);
            }

            foreach (var ppItem in model.PPItems)
            {
                if (ppItem.EntityPPItem.IsApproved)
                    continue;                
                ppService.DeleteProcurementPlanItem(ppItem.EntityPPItem.Id);
            }

            return Content(Resources.Global_String_Done);
        }

        public ActionResult RejectPP(Guid id)
        {
            ProcurementPlan pp = ppService.GetProcurementPlanById(id);
            List<Model.ProcurementPlanItem> ppItems = ppService.GetProcurementPlanItems(pp.Id);
            foreach (var ppItem in ppItems)
            {
                if (ppItem.IsApproved)
                    continue;
                ppService.DeleteProcurementPlanItem(ppItem.Id);
            }
            return Content(Resources.Global_String_Done);
        }

        #endregion

        #region .Completion Certificate.

        public ActionResult LoadCCForApproval(Guid id)
        {
            ViewCC model = CompletionCExtention.PrepareCC(id, ccService);
            return View("ApproveCC", model);
        }

        /// <summary>
        /// Approve PP
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public ActionResult ApproveCC(Guid id)
        {
            CompletionCertificate entityCC = ccService.GetCCById(id);
            entityCC.IsApproved = true;
            entityCC.ApprovedBy = currentStaff.Id;
            entityCC.ApprovedOn = DateTime.Now;
            ccService.UpdateCC(entityCC);
            //Notify preparer that CC has been approved
            notificationService.SendNotification(entityCC.Staff1.Person.OfficialEmail, string.Format(NotificationHelper.ccApprovedMsgBody, entityCC.Staff1.Person.FirstName, entityCC.RefNumber), NotificationHelper.ccsubject);            
            return Content(Resources.Global_String_Done);
        }

        public ActionResult RejectCC(Guid id)
        {
            Models.RejectCC model = new Models.RejectCC();
            CompletionCertificate cc = ccService.GetCCById(id);
            model.Id = cc.Id;
            model.RefNumber = cc.RefNumber;
            return View("RejectCC", model);
        }
        
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult RejectCC(Models.RejectCC rejectedCC)
        {
            string notificationMsg;
            CompletionCertificate entityCC = ccService.GetCCById(rejectedCC.Id);
            entityCC.IsRejected = true;
            entityCC.ApprovedBy = currentStaff.Id;
            entityCC.ApprovedOn = DateTime.Now;
            ccService.UpdateCC(entityCC);
            //Notify preparer
            notificationMsg = string.Format(NotificationHelper.ccRejectedMsgBody, entityCC.Staff1.Person.FirstName, entityCC.RefNumber, rejectedCC.RejectedRemarks);
            notificationService.SendNotification(entityCC.Staff1.Person.OfficialEmail, notificationMsg, NotificationHelper.ccsubject);
            return RejectCC(rejectedCC.Id);
        }


        #endregion

    }
}
